# _Kotlin/Native_ interoperability with Swift/Objective-C

This document covers some details of Kotlin/Native interoperability with
Swift/Objective-C.

## Usage

Kotlin/Native provides bidirectional interoperability with Objective-C.
Objective-C frameworks and libraries can be used in Kotlin code if
properly imported to the build (system frameworks are imported by default).
See e.g. "Using cinterop" in
[Gradle plugin documentation](GRADLE_PLUGIN.md#using-cinterop).
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.

Kotlin modules can be used in Swift/Objective-C code if compiled into a
framework (see "Targets and output kinds" section in [Gradle plugin documentation](GRADLE_PLUGIN.md#targets-and-output-kinds)).
See [calculator sample](https://github.com/JetBrains/kotlin-native/tree/master/samples/calculator) for an example.

## Mappings

The table below shows how Kotlin concepts are mapped to Swift/Objective-C and vice versa.

| Kotlin | Swift | Objective-C | Notes |
| ------ | ----- |------------ | ----- |
| `class` | `class` | `@interface` | [note](#name-translation) |
| `interface` | `protocol` | `@protocol` | |
| `constructor`/`create` | Initializer | Initializer | [note](#initializers) |
| Property | Property | Property | [note](#top-level-functions-and-properties) [note](#setters)|
| Method | Method | Method | [note](#top-level-functions-and-properties) [note](#method-names-translation) |
| `@Throws` | `throws` | `error:(NSError**)error` | [note](#errors-and-exceptions) |
| Extension | Extension | Category member | [note](#category-members) |
| `companion` member <- | Class method or property | Class method or property |  |
| `null` | `nil` | `nil` | |
| `Singleton` | `Singleton()`  | `[Singleton singleton]` | [note](#kotlin-singletons) |
| Primitive type | Primitive type / `NSNumber` | | [note](#nsnumber) |
| `Unit` return type | `Void` | `void` | |
| `String` | `String` | `NSString` | |
| `String` | `NSMutableString` | `NSMutableString` | [note](#nsmutablestring) |
| `List` | `Array` | `NSArray` | |
| `MutableList` | `NSMutableArray` | `NSMutableArray` | |
| `Set` | `Set` | `NSSet` | |
| `MutableSet` | `NSMutableSet` | `NSMutableSet` | [note](#collections) |
| `Map` | `Dictionary` | `NSDictionary` | |
| `MutableMap` | `NSMutableDictionary` | `NSMutableDictionary` | [note](#collections) |
| Function type | Function type | Block pointer type | [note](#function-types) |
| Suspend functions| Unsupported| Unsupported| [note](#unsupported) |
| Inline classes | Unsupported| Unsupported| [note](#unsupported) |


### Name translation

Objective-C classes are imported into Kotlin with their original names.
Protocols are imported as interfaces with `Protocol` name suffix,
i.e. `@protocol Foo` -> `interface FooProtocol`.
These classes and interfaces are placed into a package [specified in build configuration](#usage)
(`platform.*` packages for preconfigured system frameworks).

The names of Kotlin classes and interfaces are prefixed when imported to Objective-C.
The prefix is derived from the framework name.

### Initializers

Swift/Objective-C initializers are imported to Kotlin as constructors and factory methods
named `create`. The latter happens with initializers declared in the Objective-C category or
as a Swift extension, because Kotlin has no concept of extension constructors.

Kotlin constructors are imported as initializers to Swift/Objective-C. 

### Setters

Writeable Objective-C properties overriding read-only properties of the superclass are represented as `setFoo()` method for the property `foo`. Same goes for a protocol's read-only properties that are implemented as mutable.

### Top-level functions and properties

Top-level Kotlin functions and properties are accessible as members of special classes.
Each Kotlin file is translated into such a class. E.g.

<div class="sample" markdown="1" theme="idea" data-highlight-only>

```kotlin
// MyLibraryUtils.kt
package my.library

fun foo() {}
```

</div>

can be called from Swift like

<div class="sample" markdown="1" theme="idea" mode="swift">

```swift
MyLibraryUtilsKt.foo()
```

</div>

### Method names translation

Generally Swift argument labels and Objective-C selector pieces are mapped to Kotlin
parameter names. Anyway these two concepts have different semantics, so sometimes
Swift/Objective-C methods can be imported with a clashing Kotlin signature. In this case
the clashing methods can be called from Kotlin using named arguments, e.g.:

<div class="sample" markdown="1" theme="idea" mode="swift">

```swift
[player moveTo:LEFT byMeters:17]
[player moveTo:UP byInches:42]
```

</div>

in Kotlin it would be:

<div class="sample" markdown="1" theme="idea" data-highlight-only>

```kotlin
player.moveTo(LEFT, byMeters = 17)
player.moveTo(UP, byInches = 42)
```

</div>

### Errors and exceptions

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 a Kotlin method
which throws an exception to be handled, then the Kotlin method should be marked
with a `@Throws` annotation specifying a list of "expected" exception classes.

When compiling to Objective-C/Swift framework, functions having or inheriting
`@Throws` annotation are represented as `NSError*`-producing methods in Objective-C
and as `throws` methods in Swift.

When Kotlin function called from Swift/Objective-C code throws an exception
which is an instance of one of the `@Throws`-specified classes or their subclasses,
it is propagated as `NSError`. Other Kotlin exceptions reaching Swift/Objective-C
are considered unhandled and cause program termination.

Note that the opposite reversed translation is not implemented yet:
Swift/Objective-C error-throwing methods aren't imported to Kotlin as
exception-throwing.

### Category members

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.
And the extension initializers aren't available as Kotlin constructors.

### Kotlin singletons

Kotlin singleton (made with an `object` declaration, including `companion object`)
is imported to Swift/Objective-C as a class with a single instance.
The instance is available through the factory method, i.e. as
`[MySingleton mySingleton]` in Objective-C and `MySingleton()` in Swift.

### NSNumber

Kotlin primitive type boxes are mapped to special Swift/Objective-C classes.
For example, `kotlin.Int` box is represented as `KotlinInt` class instance in Swift
(or `${prefix}Int` instance in Objective-C, where `prefix` is the framework names prefix).
These classes are derived from `NSNumber`, so the instances are proper `NSNumber`s
supporting all corresponding operations.

`NSNumber` type is not automatically translated 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
about a wrapped primitive value type, i.e. `NSNumber` is statically not known
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)).

### NSMutableString

`NSMutableString` Objective-C class is not available from Kotlin.
All instances of `NSMutableString` are copied when passed to Kotlin.

### Collections

Kotlin collections are converted to Swift/Objective-C collections as described
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
a Kotlin `MutableSet`. To pass an object for Kotlin `MutableSet`,
you can create this kind of Kotlin collection explicitly by either creating it 
in Kotlin with e.g. `mutableSetOf()`, or using the `KotlinMutableSet` class in Swift 
(or `${prefix}MutableSet` in Objective-C, where `prefix` is the framework names prefix).
The same holds for `MutableMap`.

### Function types

Kotlin function-typed objects (e.g. lambdas) are converted to 
Swift functions / Objective-C blocks. However there is a difference in how
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
boxed representation. Kotlin `Unit` return value is represented
as a corresponding `Unit` singleton in Swift/Objective-C. The value of this singleton
can be retrieved in the same way as it is for any other Kotlin `object`
(see singletons in the table above).
To sum the things up:

<div class="sample" markdown="1" theme="idea" data-highlight-only>

```kotlin
fun foo(block: (Int) -> Unit) { ... }
```

</div>

would be represented in Swift as

<div class="sample" markdown="1" theme="idea" mode="swift">

```swift
func foo(block: (KotlinInt) -> KotlinUnit)
```

</div>

and can be called like

<div class="sample" markdown="1" theme="idea" data-highlight-only>

```kotlin
foo {
    bar($0 as! Int32)
    return KotlinUnit()
}
```

</div>

### Generics

Objective-C supports "lightweight generics" defined on classes, with a relatively limited feature set. Swift can import 
generics defined on classes to help provide additional type information to the compiler.

Generic feature support for Objective-C and Swift differ from Kotlin, so the translation will inevitably lose some information,
but the features supported retain meaningful information.

#### Limitations

Objective-C generics do not support all features of either Kotlin or Swift, so there will be some information lost
in the translation.

Generics can only be defined on classes, not on interfaces (protocols in Objective-C and Swift) or functions.

#### Nullability

Kotlin and Swift both define nullability as part of the type specification, while Objective-C defines nullability on methods
and properties of a type. As such, the following:

<div class="sample" markdown="1" theme="idea" data-highlight-only>

```kotlin
class Sample<T>() {
  fun myVal(): T
}
```

</div>

will (logically) look like this:

<div class="sample" markdown="1" theme="idea" mode="swift">

```swift
class Sample<T>() {
  fun myVal(): T?
}
```

</div>

In order to support a potentially nullable type, the Objective-C header needs to define `myVal` with a nullable return value.

To mitigate this, when defining your generic classes, if the generic type should *never* be null, provide a non-null 
type constraint:

<div class="sample" markdown="1" theme="idea" data-highlight-only>

```kotlin
class Sample<T : Any>() {
  fun myVal(): T
}
```

</div>

That will force the Objective-C header to mark `myVal` as non-null.

#### Variance

Objective-C allows generics to be declared covariant or contravariant. Swift has no support for variance. Generic classes coming
from Objective-C can be force-cast as needed.

<div class="sample" markdown="1" theme="idea" data-highlight-only>

```kotlin
data class SomeData(val num: Int = 42) : BaseData()
class GenVarOut<out T : Any>(val arg: T)
```

</div>

<div class="sample" markdown="1" theme="idea" mode="swift">

```swift
let variOut = GenVarOut<SomeData>(arg: sd)
let variOutAny : GenVarOut<BaseData> = variOut as! GenVarOut<BaseData>
```

</div>

#### Constraints

In Kotlin you can provide upper bounds for a generic type. Objective-C also supports this, but that support is unavailable 
in more complex cases, and is currently not supported in the Kotlin - Objective-C interop. The exception here being a non-null
upper bound will make Objective-C methods/properties non-null.

### To disable

To have the framework header written without generics, add the flag to the compiler config:

<div class="sample" markdown="1" theme="idea" data-highlight-only>

```kotlin
binaries.framework {
     freeCompilerArgs += "-Xno-objc-generics"
}
```

</div>

## Casting between mapped types

When writing Kotlin code, an object may need to be converted from a Kotlin type
to the equivalent Swift/Objective-C type (or vice versa). In this case a plain old
Kotlin cast can be used, e.g.

<div class="sample" markdown="1" theme="idea" data-highlight-only>

```kotlin
val nsArray = listOf(1, 2, 3) as NSArray
val string = nsString as String
val nsNumber = 42 as NSNumber
```

</div>

## Subclassing

### Subclassing Kotlin classes and interfaces from Swift/Objective-C

Kotlin classes and interfaces can be subclassed by Swift/Objective-C classes
and protocols.

### Subclassing Swift/Objective-C classes and protocols from Kotlin

Swift/Objective-C classes and protocols can be subclassed with a Kotlin `final` class.
Non-`final` Kotlin classes inheriting Swift/Objective-C types aren't supported yet, so it is
not possible to declare a complex class hierarchy inheriting Swift/Objective-C types.

Normal methods can be overridden using the `override` Kotlin keyword. In this case
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`. 
Initializers imported as Kotlin constructors can be overridden by Kotlin constructors
marked with the `@OverrideInit` annotation:

<div class="sample" markdown="1" theme="idea" mode="swift">

```swift
class ViewController : UIViewController {
    @OverrideInit constructor(coder: NSCoder) : super(coder)

    ...
}
```

</div>

The overriding constructor must have the same parameter names and types as the overridden one.

To override different methods with clashing Kotlin signatures, you can add a
`@Suppress("CONFLICTING_OVERLOADS")` annotation to the class.

By default the Kotlin/Native compiler doesn't allow calling a non-designated
Objective-C initializer as a `super(...)` constructor. This behaviour can be
inconvenient if the designated initializers aren't marked properly in the Objective-C
library. Adding a `disableDesignatedInitializerChecks = true` to the `.def` file for
this library would disable these compiler checks.

## 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.).

## Unsupported

Some features of Kotlin programming language are not yet mapped into respective features of Objective-C or Swift.
Currently, following features are not properly exposed in generated framework headers:
   * suspend functions
   * inline classes (arguments are mapped as either underlying primitive type or `id`)
   * custom classes implementing standard Kotlin collection interfaces (`List`, `Map`, `Set`) and other special classes
   * Kotlin subclasses of Objective-C classes
