[//]: # (title: Kotlin/Native as an Apple framework – tutorial)

> The Objective-C libraries import is in [Beta](native-c-interop-stability.md).
> All Kotlin declarations generated by the cinterop tool from Objective-C libraries
> should have the `@ExperimentalForeignApi` annotation.
>
> Native platform libraries shipped with Kotlin/Native (like Foundation, UIKit, and POSIX)
> require opt-in only for some APIs.
>
{style="note"}

Kotlin/Native provides bidirectional interoperability with Swift/Objective-C. You can both use Objective-C frameworks
and libraries in Kotlin code, and Kotlin modules in Swift/Objective-C code. 

Kotlin/Native comes with a set of pre-imported system frameworks; it's also possible to import an existing framework and
use it from Kotlin. In this tutorial, you'll learn how to create your own framework and use Kotlin/Native code from
Swift/Objective-C applications on macOS and iOS.

In this tutorial, you will:

* [Create a Kotlin library and compile it to a framework](#create-a-kotlin-library)
* [Examine the generated Swift/Objective-C API code](#generated-framework-headers)
* [Use the framework from Objective-C](#use-code-from-objective-c)
* [Use the framework from Swift](#use-code-from-swift)

You can use the command line to generate a Kotlin framework, either directly or with a script file (such as `.sh` or `.bat` file).
However, this approach doesn't scale well for larger projects that have hundreds of files and libraries.
Using a build system simplifies the process by downloading and caching the Kotlin/Native
compiler binaries and libraries with transitive dependencies, as well as by running the compiler and tests.
Kotlin/Native can use the [Gradle](https://gradle.org) build system through the [Kotlin Multiplatform plugin](gradle-configure-project.md#targeting-multiple-platforms).

> If you use a Mac and want to create and run applications for iOS or other Apple targets, you also need to
> install the [Xcode Command Line Tools](https://developer.apple.com/download/), launch it, and accept the license terms first.
>
{style="note"}

## Create a Kotlin library

> See the [Get started with Kotlin/Native](native-get-started.md#using-gradle) tutorial for detailed first steps
> and instructions on how to create a new Kotlin/Native project and open it in IntelliJ IDEA.
>
{style="tip"}

The Kotlin/Native compiler can produce a framework for macOS and iOS from the Kotlin code. The created framework contains
all declarations and binaries needed to use it with Swift/Objective-C.

Let's first create a Kotlin library:

1. In the `src/nativeMain/kotlin` directory, create the `lib.kt` file with the library contents:

   ```kotlin
   package example
    
   object Object {
       val field = "A"
   }
    
   interface Interface {
       fun iMember() {}
   }
    
   class Clazz : Interface {
       fun member(p: Int): ULong? = 42UL
   }
    
   fun forIntegers(b: Byte, s: UShort, i: Int, l: ULong?) { }
   fun forFloats(f: Float, d: Double?) { }
    
   fun strings(str: String?) : String {
       return "That is '$str' from C"
   }
    
   fun acceptFun(f: (String) -> String?) = f("Kotlin/Native rocks!")
   fun supplyFun() : (String) -> String? = { "$it is cool!" }
   ```

2. Update your `build.gradle(.kts)` Gradle build file with the following:

    <tabs group="build-script">
    <tab title="Kotlin" group-key="kotlin">
    
    ```kotlin
    plugins {
        kotlin("multiplatform") version "%kotlinVersion%"
    }
    
    repositories {
        mavenCentral()
    }
    
    kotlin {
        iosArm64("native") {
            binaries {
                framework {
                    baseName = "Demo"
                }
            }
        }
    }
    
    tasks.wrapper {
        gradleVersion = "%gradleVersion%"
        distributionType = Wrapper.DistributionType.ALL
    }
    ```
    
    </tab>
    <tab title="Groovy" group-key="groovy">
    
    ```groovy
    plugins {
        id 'org.jetbrains.kotlin.multiplatform' version '%kotlinVersion%'
    }
    
    repositories {
        mavenCentral()
    }
    
    kotlin {
        iosArm64("native") {
            binaries {
                framework {
                    baseName = "Demo"
                }
            }
        }
    }
    
    wrapper {
        gradleVersion = "%gradleVersion%"
        distributionType = "ALL"
    }
    ```
    
    </tab>
    </tabs>

    The `binaries {}` block configures the project to generate a dynamic or shared library.

    Kotlin/Native supports the `iosArm64`, `iosX64`, and `iosSimulatorArm64` targets for iOS, as well as `macosArm64` and
    `macosX64` targets for macOS. So, you can replace the `iosArm64()` with the respective Gradle function for your
    target platform:

    | Target platform/device | Gradle function       |
    |------------------------|-----------------------|
    | macOS ARM64            | `macosArm64()`        |
    | macOS x86_64           | `macosX64()`          |
    | iOS ARM64              | `iosArm64()`          |
    | iOS Simulator (ARM64)  | `iosSimulatorArm64()` |
    | iOS Simulator (x86_64) | `iosX64()`            |

    For information on other supported Apple targets, see [Kotlin/Native target support](native-target-support.md).

3. Run the `linkDebugFrameworkNative` Gradle task in the IDE or use the following console command in your terminal to
   build the framework:

   ```bash
   ./gradlew linkDebugFrameworkNative
   ```
    
The build generates the framework into the `build/bin/native/debugFramework` directory.

> You can also use the `linkNative` Gradle task to generate both `debug` and `release` variants of the framework.
>
{style="tip"}

## Generated framework headers

Each framework variant contains a header file. The headers don't depend on the target platform. Header files contain
definitions for your Kotlin code and a few Kotlin-wide declarations. Let's see what's inside.

### Kotlin/Native runtime declarations

In the `build/bin/native/debugFramework/Demo.framework/Headers` directory, open the `Demo.h` header file.
Take a look at Kotlin runtime declarations:

```objc
NS_ASSUME_NONNULL_BEGIN
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunknown-warning-option"
#pragma clang diagnostic ignored "-Wincompatible-property-type"
#pragma clang diagnostic ignored "-Wnullability"

#pragma push_macro("_Nullable_result")
#if !__has_feature(nullability_nullable_result)
#undef _Nullable_result
#define _Nullable_result _Nullable
#endif

__attribute__((swift_name("KotlinBase")))
@interface DemoBase : NSObject
- (instancetype)init __attribute__((unavailable));
+ (instancetype)new __attribute__((unavailable));
+ (void)initialize __attribute__((objc_requires_super));
@end

@interface DemoBase (DemoBaseCopying) <NSCopying>
@end

__attribute__((swift_name("KotlinMutableSet")))
@interface DemoMutableSet<ObjectType> : NSMutableSet<ObjectType>
@end

__attribute__((swift_name("KotlinMutableDictionary")))
@interface DemoMutableDictionary<KeyType, ObjectType> : NSMutableDictionary<KeyType, ObjectType>
@end

@interface NSError (NSErrorDemoKotlinException)
@property (readonly) id _Nullable kotlinException;
@end
```

Kotlin classes have a `KotlinBase` base class in Swift/Objective-C that extends the `NSObject` class there.
There are also wrappers for collections and exceptions. Most of the collection types are mapped to similar collection
types in Swift/Objective-C:

| Kotlin      | Swift               | Objective-C         |
|-------------|---------------------|---------------------|
| List        | Array               | NSArray             |
| MutableList | NSMutableArray      | NSMutableArray      |
| Set         | Set                 | NSSet               |
| MutableSet  | NSMutableSet        | NSMutableSet        |
| Map         | Dictionary          | NSDictionary        |
| MutableMap  | NSMutableDictionary | NSMutableDictionary |

### Kotlin numbers and NSNumber

The next part of the `Demo.h` file contains type mappings between Kotlin/Native number types and `NSNumber`. The base
class is called `DemoNumber` in Objective-C and `KotlinNumber` in Swift. It extends `NSNumber`.

For each Kotlin number type, there is a corresponding predefined child class:

| Kotlin    | Swift           | Objective-C        | Simple type          |
|-----------|-----------------|--------------------|----------------------|
| `-`       | `KotlinNumber`  | `<Package>Number`  | `-`                  |
| `Byte`    | `KotlinByte`    | `<Package>Byte`    | `char`               |
| `UByte`   | `KotlinUByte`   | `<Package>UByte`   | `unsigned char`      |
| `Short`   | `KotlinShort`   | `<Package>Short`   | `short`              |
| `UShort`  | `KotlinUShort`  | `<Package>UShort`  | `unsigned short`     |
| `Int`     | `KotlinInt`     | `<Package>Int`     | `int`                |
| `UInt`    | `KotlinUInt`    | `<Package>UInt`    | `unsigned int`       |
| `Long`    | `KotlinLong`    | `<Package>Long`    | `long long`          |
| `ULong`   | `KotlinULong`   | `<Package>ULong`   | `unsigned long long` |
| `Float`   | `KotlinFloat`   | `<Package>Float`   | `float`              |
| `Double`  | `KotlinDouble`  | `<Package>Double`  | `double`             |
| `Boolean` | `KotlinBoolean` | `<Package>Boolean` | `BOOL/Bool`          |

Every number type has a class method to create a new instance from the corresponding simple type. Also, there is an instance
method to extract a simple value back. Schematically, all such declarations look like that:

```objc
__attribute__((swift_name("Kotlin__TYPE__")))
@interface Demo__TYPE__ : DemoNumber
- (instancetype)initWith__TYPE__:(__CTYPE__)value;
+ (instancetype)numberWith__TYPE__:(__CTYPE__)value;
@end;
```

Here, `__TYPE__` is one of the simple type names, and `__CTYPE__` is the corresponding Objective-C type,
for example, `initWithChar(char)`.

These types are used to map boxed Kotlin number types to Swift/Objective-C.
In Swift, you can call the constructor to create an instance, for example, `KotlinLong(value: 42)`.

### Classes and objects from Kotlin

Let's see how `class` and `object` are mapped to Swift/Objective-C. The generated `Demo.h` file contains the exact
definitions for `Class`, `Interface`, and `Object`:

```objc
__attribute__((swift_name("Interface")))
@protocol DemoInterface
@required
- (void)iMember __attribute__((swift_name("iMember()")));
@end

__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("Clazz")))
@interface DemoClazz : DemoBase <DemoInterface>
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
- (DemoULong * _Nullable)memberP:(int32_t)p __attribute__((swift_name("member(p:)")));
@end

__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("Object")))
@interface DemoObject : DemoBase
+ (instancetype)alloc __attribute__((unavailable));
+ (instancetype)allocWithZone:(struct _NSZone *)zone __attribute__((unavailable));
+ (instancetype)object __attribute__((swift_name("init()")));
@property (class, readonly, getter=shared) DemoObject *shared __attribute__((swift_name("shared")));
@property (readonly) NSString *field __attribute__((swift_name("field")));
@end
```

Objective-C attributes in this code help use the framework from both Swift and Objective-C
languages. `DemoInterface`, `DemoClazz`, and `DemoObject` are created for `Interface`, `Clazz`, and `Object`, respectively.

The `Interface` is turned into `@protocol`, while both a `class` and an `object` are represented as `@interface`. The
`Demo` prefix comes from the framework name. The nullable return type `ULong?` is turned into `DemoULong` in Objective-C.

### Global declarations from Kotlin

All global functions from Kotlin are turned into `DemoLibKt` in Objective-C and into `LibKt` in Swift,
where `Demo` is the framework name set by the `-output` parameter of `kotlinc-native`:

```objc
__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("LibKt")))
@interface DemoLibKt : DemoBase
+ (NSString * _Nullable)acceptFunF:(NSString * _Nullable (^)(NSString *))f __attribute__((swift_name("acceptFun(f:)")));
+ (void)forFloatsF:(float)f d:(DemoDouble * _Nullable)d __attribute__((swift_name("forFloats(f:d:)")));
+ (void)forIntegersB:(int8_t)b s:(uint16_t)s i:(int32_t)i l:(DemoULong * _Nullable)l __attribute__((swift_name("forIntegers(b:s:i:l:)")));
+ (NSString *)stringsStr:(NSString * _Nullable)str __attribute__((swift_name("strings(str:)")));
+ (NSString * _Nullable (^)(NSString *))supplyFun __attribute__((swift_name("supplyFun()")));
@end
```

Kotlin `String` and Objective-C `NSString*` are mapped transparently. Similarly, `Unit` type from Kotlin is mapped to `void`.
The primitive types are mapped directly. Non-nullable primitive types are mapped transparently.
Nullable primitive types are mapped to `Kotlin<TYPE>*` types, as shown in the [table](#kotlin-numbers-and-nsnumber). 
Both higher-order functions `acceptFunF` and `supplyFun` are included and accept Objective-C blocks.

You can find more information about type mapping in [Interoperability with Swift/Objective-C](native-objc-interop.md#mappings).

## Garbage collection and reference counting

Swift and Objective-C use automatic reference counting (ARC). Kotlin/Native has its own [garbage collector](native-memory-manager.md#garbage-collector),
which is also [integrated with Swift/Objective-C ARC](native-arc-integration.md).

Unused Kotlin objects are automatically removed. You don't need to take additional steps to control the lifetime of
Kotlin/Native instances from Swift or Objective-C.

## Use code from Objective-C

Let's call the framework from Objective-C. In the framework directory, create the `main.m` file with the following code:

```objc 
#import <Foundation/Foundation.h>
#import <Demo/Demo.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        [DemoObject.shared field];
        
        DemoClazz* clazz = [[ DemoClazz alloc] init];
        [clazz memberP:42];
        
        [DemoLibKt forIntegersB:1 s:1 i:3 l:[DemoULong numberWithUnsignedLongLong:4]];
        [DemoLibKt forIntegersB:1 s:1 i:3 l:nil];
        
        [DemoLibKt forFloatsF:2.71 d:[DemoDouble numberWithDouble:2.71]];
        [DemoLibKt forFloatsF:2.71 d:nil];
        
        NSString* ret = [DemoLibKt acceptFunF:^NSString * _Nullable(NSString * it) {
            return [it stringByAppendingString:@" Kotlin is fun"];
        }];
        
        NSLog(@"%@", ret);
        return 0;
    }
}
```

Here, you call Kotlin classes directly from Objective-C code. A Kotlin object uses the `<object name>.shared` class
property, which allows you to get the object's only instance and call object methods on it.

The widespread pattern is used to create an instance of the `Clazz` class. You call the `[[ DemoClazz alloc] init]` on
Objective-C. You can also use `[DemoClazz new]` for constructors without parameters.

Global declarations from the Kotlin sources are scoped under the `DemoLibKt` class in Objective-C.
All Kotlin functions are turned into class methods of that class.

The `strings` function is turned into `DemoLibKt.stringsStr` function in Objective-C, so you can pass `NSString`
directly to it. The return value is visible as `NSString` too.

## Use code from Swift

The framework you generated has helper attributes to make it easier to use with Swift. Let's convert the [previous
Objective-C example](#use-code-from-objective-c) into Swift.

In the framework directory, create the `main.swift` file with the following code:

```swift
import Foundation
import Demo

let kotlinObject = Object.shared

let field = Object.shared.field

let clazz = Clazz()
clazz.member(p: 42)

LibKt.forIntegers(b: 1, s: 2, i: 3, l: 4)
LibKt.forFloats(f: 2.71, d: nil)

let ret = LibKt.acceptFun { "\($0) Kotlin is fun" }
if (ret != nil) {
    print(ret!)
}
``` 

There are some small differences between the original Kotlin code and its Swift version. In Kotlin, any object declaration
has only one instance. The `Object.shared` syntax is used to access this single instance.

Kotlin function and property names are translated as is. Kotlin's `String` is turned into Swift's `String`. Swift
hides `NSNumber*` boxing too. You can also pass a Swift closure to Kotlin and call a Kotlin lambda function from Swift. 

You can find more information about type mapping in [Interoperability with Swift/Objective-C](native-objc-interop.md#mappings).

## Connect the framework to your iOS project

Now you can connect the generated framework to your iOS project as a dependency. There are multiple ways to set it up
and automate the process, choose the method that suits you best:

<a href="https://kotlinlang.org/docs/multiplatform/multiplatform-ios-integration-overview.html"><img src="choose-ios-integration.svg" width="700" alt="Choose iOS integration method" style="block"/></a>

## What's next

* [Learn more about interoperability with Objective-C](native-objc-interop.md)
* [See how interoperability with C is implemented in Kotlin](native-c-interop.md)
* [Check out the Kotlin/Native as a dynamic library tutorial](native-dynamic-libraries.md)
