proofread (#2066)
This commit is contained in:
committed by
Nikolay Igotti
parent
5b63cdb4b2
commit
a426738213
+45
-46
@@ -1,6 +1,6 @@
|
|||||||
# _Kotlin/Native_ interoperability with Swift/Objective-C
|
# _Kotlin/Native_ interoperability with Swift/Objective-C
|
||||||
|
|
||||||
This documents covers some details of Kotlin/Native interoperability with
|
This document covers some details of Kotlin/Native interoperability with
|
||||||
Swift/Objective-C.
|
Swift/Objective-C.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
@@ -10,12 +10,12 @@ Objective-C frameworks and libraries can be used in Kotlin code if
|
|||||||
properly imported to the build (system frameworks are imported by default).
|
properly imported to the build (system frameworks are imported by default).
|
||||||
See e.g. "Interop libraries" in
|
See e.g. "Interop libraries" in
|
||||||
[Gradle plugin documentation](GRADLE_PLUGIN.md#building-artifacts).
|
[Gradle plugin documentation](GRADLE_PLUGIN.md#building-artifacts).
|
||||||
Swift library can be used in Kotlin code if its API is exported to Objective-C
|
A Swift library can be used in Kotlin code if its API is exported to Objective-C
|
||||||
with `@objc`. Pure Swift modules are not yet supported.
|
with `@objc`. Pure Swift modules are not yet supported.
|
||||||
|
|
||||||
Kotlin module can be used in Swift/Objective-C code if compiled into a
|
Kotlin modules can be used in Swift/Objective-C code if compiled into a
|
||||||
[framework](GRADLE_PLUGIN.md#framework). See [calculator sample](https://github.com/JetBrains/kotlin-native/tree/master/samples/calculator)
|
[framework](GRADLE_PLUGIN.md#framework). See [calculator sample](https://github.com/JetBrains/kotlin-native/tree/master/samples/calculator)
|
||||||
as an example.
|
for an example.
|
||||||
|
|
||||||
## Mappings
|
## Mappings
|
||||||
|
|
||||||
@@ -50,17 +50,17 @@ The table below shows how Kotlin concepts are mapped to Swift/Objective-C and vi
|
|||||||
Objective-C classes are imported into Kotlin with their original names.
|
Objective-C classes are imported into Kotlin with their original names.
|
||||||
Protocols are imported as interfaces with `Protocol` name suffix,
|
Protocols are imported as interfaces with `Protocol` name suffix,
|
||||||
i.e. `@protocol Foo` -> `interface FooProtocol`.
|
i.e. `@protocol Foo` -> `interface FooProtocol`.
|
||||||
These classes and interfaces are placed into package [specified in build configuration](#usage)
|
These classes and interfaces are placed into a package [specified in build configuration](#usage)
|
||||||
(`platform.*` packages for preconfigured system frameworks).
|
(`platform.*` packages for preconfigured system frameworks).
|
||||||
|
|
||||||
Names of Kotlin classes and interfaces are prefixed when imported to Swift/Objective-C.
|
The names of Kotlin classes and interfaces are prefixed when imported to Swift/Objective-C.
|
||||||
The prefix is derived from the framework name.
|
The prefix is derived from the framework name.
|
||||||
|
|
||||||
### Initializers
|
### Initializers
|
||||||
|
|
||||||
Swift/Objective-C initializers are imported to Kotlin as constructors and factory methods
|
Swift/Objective-C initializers are imported to Kotlin as constructors and factory methods
|
||||||
named `create`. The latter happens with initializers declared in Objective-C category or
|
named `create`. The latter happens with initializers declared in the Objective-C category or
|
||||||
as Swift extension, because Kotlin has no concept of extension constructors.
|
as a Swift extension, because Kotlin has no concept of extension constructors.
|
||||||
|
|
||||||
Kotlin constructors are imported as initializers to Swift/Objective-C.
|
Kotlin constructors are imported as initializers to Swift/Objective-C.
|
||||||
|
|
||||||
@@ -93,11 +93,10 @@ Framework.foo()
|
|||||||
|
|
||||||
Generally Swift argument labels and Objective-C selector pieces are mapped to Kotlin
|
Generally Swift argument labels and Objective-C selector pieces are mapped to Kotlin
|
||||||
parameter names. Anyway these two concepts have different semantics, so sometimes
|
parameter names. Anyway these two concepts have different semantics, so sometimes
|
||||||
Swift/Objective-C methods can be imported with clashing Kotlin signature. In this case
|
Swift/Objective-C methods can be imported with a clashing Kotlin signature. In this case
|
||||||
clashing methods can be called from Kotlin using named arguments, e.g.:
|
the clashing methods can be called from Kotlin using named arguments, e.g.:
|
||||||
|
|
||||||
<div class="sample" markdown="1" theme="idea" mode="swift">
|
<div class="sample" markdown="1" theme="idea" mode="swift">
|
||||||
|
|
||||||
```swift
|
```swift
|
||||||
[player moveTo:LEFT byMeters:17]
|
[player moveTo:LEFT byMeters:17]
|
||||||
[player moveTo:UP byInches:42]
|
[player moveTo:UP byInches:42]
|
||||||
@@ -105,7 +104,7 @@ clashing methods can be called from Kotlin using named arguments, e.g.:
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
in Kotlin would be:
|
in Kotlin it would be:
|
||||||
|
|
||||||
<div class="sample" markdown="1" theme="idea" data-highlight-only>
|
<div class="sample" markdown="1" theme="idea" data-highlight-only>
|
||||||
|
|
||||||
@@ -119,13 +118,13 @@ player.moveTo(UP, byInches = 42)
|
|||||||
### Errors and exceptions
|
### Errors and exceptions
|
||||||
|
|
||||||
Kotlin has no concept of checked exceptions, all Kotlin exceptions are unchecked.
|
Kotlin has no concept of checked exceptions, all Kotlin exceptions are unchecked.
|
||||||
Swift has only checked errors. So if Swift or Objective-C code calls Kotlin method
|
Swift has only checked errors. So if Swift or Objective-C code calls a Kotlin method
|
||||||
which throws an exception to be handled, then Kotlin method should be marked
|
which throws an exception to be handled, then the Kotlin method should be marked
|
||||||
with `@Throws` annotation. In this case all Kotlin exceptions
|
with a `@Throws` annotation. In this case all Kotlin exceptions
|
||||||
(except for instances of `Error`, `RuntimeException` and subclasses) are translated to
|
(except for instances of `Error`, `RuntimeException` and subclasses) are translated into
|
||||||
Swift error/`NSError`.
|
a Swift error/`NSError`.
|
||||||
|
|
||||||
Note that the opposite translation is not implemented yet:
|
Note that the opposite reversed translation is not implemented yet:
|
||||||
Swift/Objective-C error-throwing methods aren't imported to Kotlin as
|
Swift/Objective-C error-throwing methods aren't imported to Kotlin as
|
||||||
exception-throwing.
|
exception-throwing.
|
||||||
|
|
||||||
@@ -133,12 +132,12 @@ exception-throwing.
|
|||||||
|
|
||||||
Members of Objective-C categories and Swift extensions are imported to Kotlin
|
Members of Objective-C categories and Swift extensions are imported to Kotlin
|
||||||
as extensions. That's why these declarations can't be overridden in Kotlin.
|
as extensions. That's why these declarations can't be overridden in Kotlin.
|
||||||
And extension initializers aren't available as Kotlin constructors.
|
And the extension initializers aren't available as Kotlin constructors.
|
||||||
|
|
||||||
### Kotlin singletons
|
### Kotlin singletons
|
||||||
|
|
||||||
Kotlin singleton (made with `object` declaration, including `companion object`)
|
Kotlin singleton (made with an `object` declaration, including `companion object`)
|
||||||
is imported to Swift/Objective-C as class with a single instance.
|
is imported to Swift/Objective-C as a class with a single instance.
|
||||||
The instance is available through the factory method, i.e. as
|
The instance is available through the factory method, i.e. as
|
||||||
`[MySingleton mySingleton]` in Objective-C and `MySingleton()` in Swift.
|
`[MySingleton mySingleton]` in Objective-C and `MySingleton()` in Swift.
|
||||||
|
|
||||||
@@ -146,10 +145,10 @@ The instance is available through the factory method, i.e. as
|
|||||||
|
|
||||||
While Kotlin primitive types in some cases are mapped to `NSNumber`
|
While Kotlin primitive types in some cases are mapped to `NSNumber`
|
||||||
(e.g. when they are boxed), `NSNumber` type is not automatically translated
|
(e.g. when they are boxed), `NSNumber` type is not automatically translated
|
||||||
to Kotlin primitive types when used as Swift/Objective-C parameter type or return value.
|
to Kotlin primitive types when used as a Swift/Objective-C parameter type or return value.
|
||||||
The reason is that `NSNumber` type doesn't provide enough information
|
The reason is that `NSNumber` type doesn't provide enough information
|
||||||
about wrapped primitive value type, i.e. `NSNumber` is statically not known
|
about a wrapped primitive value type, i.e. `NSNumber` is statically not known
|
||||||
to be e.g. `Byte`, `Boolean` or `Double`. So Kotlin primitive values
|
to be a e.g. `Byte`, `Boolean`, or `Double`. So Kotlin primitive values
|
||||||
should be cast to/from `NSNumber` manually (see [below](#casting-between-mapped-types)).
|
should be cast to/from `NSNumber` manually (see [below](#casting-between-mapped-types)).
|
||||||
|
|
||||||
### NSMutableString
|
### NSMutableString
|
||||||
@@ -160,11 +159,11 @@ All instances of `NSMutableString` are copied when passed to Kotlin.
|
|||||||
### Collections
|
### Collections
|
||||||
|
|
||||||
Kotlin collections are converted to Swift/Objective-C collections as described
|
Kotlin collections are converted to Swift/Objective-C collections as described
|
||||||
by the table above. Swift/Objective-C collections are mapped to Kotlin in the same way,
|
in the table above. Swift/Objective-C collections are mapped to Kotlin in the same way,
|
||||||
except for `NSMutableSet` and `NSMutableDictionary`. `NSMutableSet` isn't converted to
|
except for `NSMutableSet` and `NSMutableDictionary`. `NSMutableSet` isn't converted to
|
||||||
Kotlin `MutableSet`. To pass an object for Kotlin `MutableSet`,
|
a Kotlin `MutableSet`. To pass an object for Kotlin `MutableSet`,
|
||||||
one can create this kind of Kotlin collection explicitly by either creating it
|
you can create this kind of Kotlin collection explicitly by either creating it
|
||||||
in Kotlin with e.g. `mutableSetOf()`, or using `${prefix}MutableSet` class in
|
in Kotlin with e.g. `mutableSetOf()`, or using the `${prefix}MutableSet` class in
|
||||||
Swift/Objective-C, where `prefix` is the framework names prefix.
|
Swift/Objective-C, where `prefix` is the framework names prefix.
|
||||||
The same holds for `MutableMap`.
|
The same holds for `MutableMap`.
|
||||||
|
|
||||||
@@ -175,8 +174,8 @@ Swift functions / Objective-C blocks. However there is a difference in how
|
|||||||
types of parameters and return values are mapped when translating a function
|
types of parameters and return values are mapped when translating a function
|
||||||
and a function type. In the latter case primitive types are mapped to their
|
and a function type. In the latter case primitive types are mapped to their
|
||||||
boxed representation, `NSNumber`. Kotlin `Unit` return value is represented
|
boxed representation, `NSNumber`. Kotlin `Unit` return value is represented
|
||||||
as corresponding `Unit` singleton in Swift/Objective-C. The value of this singleton
|
as a corresponding `Unit` singleton in Swift/Objective-C. The value of this singleton
|
||||||
can be retrieved in the same way as for any other Kotlin `object`
|
can be retrieved in the same way as it is for any other Kotlin `object`
|
||||||
(see singletons in the table above).
|
(see singletons in the table above).
|
||||||
To sum the things up:
|
To sum the things up:
|
||||||
|
|
||||||
@@ -213,8 +212,8 @@ foo {
|
|||||||
|
|
||||||
## Casting between mapped types
|
## Casting between mapped types
|
||||||
|
|
||||||
When writing Kotlin code, an object may require to be converted from Kotlin type
|
When writing Kotlin code, an object may need to be converted from a Kotlin type
|
||||||
to equivalent Swift/Objective-C type (or vice versa). In this case plain old
|
to the equivalent Swift/Objective-C type (or vice versa). In this case a plain old
|
||||||
Kotlin cast can be used, e.g.
|
Kotlin cast can be used, e.g.
|
||||||
|
|
||||||
<div class="sample" markdown="1" theme="idea" data-highlight-only>
|
<div class="sample" markdown="1" theme="idea" data-highlight-only>
|
||||||
@@ -233,22 +232,22 @@ val nsNumber = 42 as NSNumber
|
|||||||
|
|
||||||
Kotlin classes and interfaces can be subclassed by Swift/Objective-C classes
|
Kotlin classes and interfaces can be subclassed by Swift/Objective-C classes
|
||||||
and protocols.
|
and protocols.
|
||||||
Currently a class that adopts Kotlin protocol should inherit `NSObject`
|
Currently a class that adopts the Kotlin protocol should inherit `NSObject`
|
||||||
(either directly or indirectly). Note that all Kotlin classes do inherit `NSObject`,
|
(either directly or indirectly). Note that all Kotlin classes do inherit `NSObject`,
|
||||||
so a Swift/Objective-C subclass of Kotlin class can adopt Kotlin protocol.
|
so a Swift/Objective-C subclass of Kotlin class can adopt the Kotlin protocol.
|
||||||
|
|
||||||
### Subclassing Swift/Objective-C classes and protocols from Kotlin
|
### Subclassing Swift/Objective-C classes and protocols from Kotlin
|
||||||
|
|
||||||
Swift/Objective-C classes and protocols can be subclassed with Kotlin `final` class.
|
Swift/Objective-C classes and protocols can be subclassed with a Kotlin `final` class.
|
||||||
Non-`final` Kotlin classes inherting Swift/Objective-C types aren't supported yet, so it is
|
Non-`final` Kotlin classes inheriting Swift/Objective-C types aren't supported yet, so it is
|
||||||
not possible to declare a complex class hierarchy inherting Swift/Objective-C types.
|
not possible to declare a complex class hierarchy inheriting Swift/Objective-C types.
|
||||||
|
|
||||||
Normal methods can be overridden using `override` Kotlin keyword. In this case
|
Normal methods can be overridden using the `override` Kotlin keyword. In this case
|
||||||
overriding method must have the same parameter names as the overridden one.
|
the overriding method must have the same parameter names as the overridden one.
|
||||||
|
|
||||||
Sometimes it is required to override initializers, e.g. when subclassing `UIViewController`.
|
Sometimes it is required to override initializers, e.g. when subclassing `UIViewController`.
|
||||||
Initializers imported as Kotlin constructors can be overridden by Kotlin constructors
|
Initializers imported as Kotlin constructors can be overridden by Kotlin constructors
|
||||||
marked with `@OverrideInit` annotation:
|
marked with the `@OverrideInit` annotation:
|
||||||
|
|
||||||
<div class="sample" markdown="1" theme="idea" mode="swift">
|
<div class="sample" markdown="1" theme="idea" mode="swift">
|
||||||
|
|
||||||
@@ -264,16 +263,16 @@ class ViewController : UIViewController {
|
|||||||
|
|
||||||
The overriding constructor must have the same parameter names and types as the overridden one.
|
The overriding constructor must have the same parameter names and types as the overridden one.
|
||||||
|
|
||||||
To override different methods with clashing Kotlin signatures, one can add
|
To override different methods with clashing Kotlin signatures, you can add a
|
||||||
`@Suppress("CONFLICTING_OVERLOADS")` annotation to the class.
|
`@Suppress("CONFLICTING_OVERLOADS")` annotation to the class.
|
||||||
|
|
||||||
By default Kotlin/Native compiler doesn't allow to call non-designated
|
By default the Kotlin/Native compiler doesn't allow calling a non-designated
|
||||||
Objective-C initializer as `super(...)` constructor. This behaviour can be
|
Objective-C initializer as a `super(...)` constructor. This behaviour can be
|
||||||
inconvenient if designated initializers aren't marked properly in the Objective-C
|
inconvenient if the designated initializers aren't marked properly in the Objective-C
|
||||||
library. Adding `disableDesignatedInitializerChecks = true` to `.def` file for
|
library. Adding a `disableDesignatedInitializerChecks = true` to the `.def` file for
|
||||||
this library would disable these compiler checks.
|
this library would disable these compiler checks.
|
||||||
|
|
||||||
## C features
|
## C features
|
||||||
|
|
||||||
See [INTEROP.md](INTEROP.md) for the case when library uses some plain C features
|
See [INTEROP.md](INTEROP.md) for an example case where the library uses some plain C features
|
||||||
(e.g. unsafe pointers, structs etc.).
|
(e.g. unsafe pointers, structs etc.).
|
||||||
|
|||||||
Reference in New Issue
Block a user