# Quickstart in iOS Swift

In this quickstart guide, we will be integrating the ARwayKit SDK with iOS Swift. This example will be using [Unity as a Library](https://github.com/Unity-Technologies/uaal-example/blob/uaal-example/19LTS-21LTS/docs/ios.md) to integrate into an iOS app.

## Installed Versions

In this guide, we will be using the following versions:

* Xcode: 14.3
* Unity: 2022.3.29f1 LST

## Download the ARwayKit SDK

Download the ARwayKit SDK project from GitHub as a **ZIP**. You can [contact us](https://www.arway.ai/contact) for access to the ARwayKit SDK.

## Create a Basic Project in Xcode

For this example a new iOS app called "SwiftUnity" will be created with interface "Storyboard" and language "Swift".

## Generate the Build for the iOS Platform

{% hint style="info" %}
Make sure to add the Account ID and Secret Key variables to the Unity project. Follow the guide for [Building from the Source Code](/arway-sdk/building-from-the-source-code.md) for instructions.
{% endhint %}

### **Updating the** Addressables Groups

When opening the project in Unity for the first time, you will need to build the Addressables Groups.

1. Switch the build platform to either iOS or Android
   * "File-> Build Settings..." then select the Android or iOS as the Platform.
2. Click "Switch Platform" on the bottom right.
3. Navigate to "Window -> Asset Management -> Addressable -> Groups".
4. In the Addressables Groups window, click on "Build -> New Build -> Default Build Script".
5. In the Console window, you should see the success message "Addressable content successfully built".

{% hint style="info" %}
When making any changes that affect localization strings, you will need to update the Addressables Groups.
{% endhint %}

### **Building the Project**

**Steps**

1. In Unity select File -> Build Settings.
2. Switch the Platform to iOS.
3. Select option "Build Project".

<figure><img src="/files/3tK8dGP7e4O9aOiIK8DU" alt=""><figcaption><p>Build the project, this example will run it as debug.</p></figcaption></figure>

4. Export the ARwayKit Unity SDK to a new folder and name it "iOSBuild" and place it in the base directory for the iOS project.

## **Setup Xcode workspace**

Xcode workspace allows to work on multiple projects simultaneously and combine their products

1. Open your Xcode project.
2. Create workspace and save it as both.xcworkspace. (File / New / Workspace).\
   ![](/files/qbAnwcTPIHgVaTlPjSvP)
3. All the steps are done from just created Workspace project.
4. Add SwiftUnity.xcodeproj and generated Unity-iPhone.xcodeproj from step #2 to workspace on a same level ( File / Add Files to “both” ).\
   ![](/files/riwous86HLKUut8fW4wB)

### **Add UnityFramework.framework**

With this step we add Unity player in the form of a framework to NativeiOSApp, it does not change the behavior of NativeiOSApp yet

1. Select NativeiOSApp target from NativeiOSApp project.
2. In "General" tab / "Frameworks, Libraries, and Embedded Content" press **+**.
3. Add Unity-iPhone/UnityFramework.framework.

   <figure><img src="/files/CjQokQ1x9cuz5CSXgxfd" alt=""><figcaption></figcaption></figure>
4. In "Build Phases" tab, expand "Link Binary With Libraries".
5. Remove UnityFramework.framework from the list (select it and press **-** ).

   <figure><img src="/files/7dNxEUmAqGciY6EYfCQX" alt=""><figcaption></figcaption></figure>

### **Make Data folder to be part of the UnityFramework**

By default Data folder is part of Unity-iPhone target, we change that to make everything encapsulated in one single framework file.

1. Change Target Membership for Data folder to UnityFramework.

   <figure><img src="/files/XfKk2hbsbZkwSAPnp1a8" alt=""><figcaption></figcaption></figure>

Next, open **Info.plist** and add the following rows:

* Privacy - Microphone Usage Description: Used for creating audio content
* Privacy - Camera Usage Description: Used for AR Content and mapping
* Privacy - Location Usage Description: Used to attach maps with global coordinates and public map searching
* Privacy - Location When in Usage Description: Used to attach maps with global coordinates and public map searching
* Privacy - Photo Library Usage Description: This app requires access to save media
* Privacy - Photo Library Additions Usage Description: This app requires access to save media

<figure><img src="/files/rFqMGDFZo0lZlCucxJ4J" alt=""><figcaption></figcaption></figure>

### Swift Code

To create an entry point to SwiftUI, create a new SwiftUI view called **ContentView\.swift** and add a single button to launch ARway.

{% code title="ContentView\.swift" %}

```swift
import SwiftUI

struct ContentView: View {
    var body: some View {
        Button(action: {
            Unity.shared.show()
        }) {
            Text("Launch ARway!")
        }
    }
}
```

{% endcode %}

Next, update the **ViewController.swift** file to match the following.

{% code title="ViewController.swift" %}

```swift
import UIKit
import SwiftUI

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let vc = UIHostingController(rootView: ContentView())
        addChild(vc)
        vc.view.frame = self.view.frame
        view.addSubview(vc.view)
        vc.didMove(toParent: self)
    }
}

```

{% endcode %}

Next, implement the connection between the Unity SDK and the Swift app. A new singleton called **Unity.swift** is created with the following code.

{% code title="Unity.swift" %}

```swift
import Foundation
import UnityFramework

class Unity: UIResponder, UIApplicationDelegate {
    static let shared = Unity()

    private let dataBundleId = "com.unity3d.framework"
    private let frameworkPath = "/Frameworks/UnityFramework.framework"

    private lazy var unityFramework: UnityFramework? = {
        guard let bundle = loadUnityFramework() else {
            return nil
        }
        let ufw = bundle.principalClass?.getInstance()
        ufw?.setDataBundleId(dataBundleId)
        ufw?.register(self)
        return ufw
    }()

    private var hostMainWindow: UIWindow?

    private var isInitialized: Bool {
        unityFramework?.appController() != nil
    }

    func show() {
        guard isInitialized else {
            initWindow()
            return
        }
        showWindow()
    }

    func setHostMainWindow(_ hostMainWindow: UIWindow?) {
        self.hostMainWindow = hostMainWindow
    }

    private func initWindow() {
        guard !isInitialized else {
            showWindow()
            return
        }
        guard let unityFramework = unityFramework else {
            print("ERROR: Was not able to load Unity")
            return unloadWindow()
        }
        self.unityFramework = unityFramework
        unityFramework.runEmbedded(withArgc: CommandLine.argc, argv: CommandLine.unsafeArgv, appLaunchOpts: nil)
    }

    private func showWindow() {
        guard let unityFramework = unityFramework else {
            return
        }
        unityFramework.showUnityWindow()
    }

    private func unloadWindow() {
        guard let unityFramework = unityFramework else {
            return
        }
        unityFramework.unloadApplication()
    }

    private func loadUnityFramework() -> Bundle? {
        let bundlePath = Bundle.main.bundlePath + frameworkPath
        guard let bundle = Bundle(path: bundlePath), !bundle.isLoaded else {
            return nil
        }
        do {
            try bundle.loadAndReturnError()
        } catch {
            print("ERROR: Failed to load Unity framework: \(error)")
            return nil
        }
        guard unityFramework?.appController() == nil else {
            return bundle
        }
        let machineHeader = UnsafeMutablePointer<MachHeader>.allocate(capacity: 1)
        machineHeader.pointee = _mh_execute_header
        unityFramework?.setExecuteHeader(machineHeader)
        return bundle
    }
}

extension Unity: UnityFrameworkListener {
    func unityDidUnload(_ notification: Notification!) {
        unityFramework?.unregisterFrameworkListener(self)
        unityFramework = nil
        hostMainWindow?.makeKeyAndVisible()
    }
}
```

{% endcode %}

Next update the **AppDelegate.swift** file to pass the main window reference to Unity.

{% code title="AppDelegate.swift" %}

```swift
import UIKit

@main
class AppDelegate: UIResponder, UIApplicationDelegate {
    var window: UIWindow?
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        Unity.shared.setHostMainWindow(window)
        return true
    }
}
```

{% endcode %}

You should now be able to build and run the project on an iOS device.

{% hint style="info" %}
To run the app, you will need to use a physical device and not a simulator.
{% endhint %}

{% hint style="info" %}
Additional information about integrating Unity as a library into a standard iOS app can be found in the following links:&#x20;

<https://github.com/Unity-Technologies/uaal-example/blob/uaal-example/19LTS-21LTS/docs/ios.md>

<https://docs.unity3d.com/2019.3/Documentation/Manual/UnityasaLibrary.html>
{% endhint %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.arway.ai/arwaykit-sdk-integrations/ios-swift/quickstart-in-ios-swift.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
