Version: Unity 6.7 Alpha (6000.7)
Language : English
Introduction to the Swift Xcode project type for iOS and tvOS
Structure of a Unity Xcode Swift project type

Migrate to a Swift Xcode project type

Migrate your existing Unity iOS project from the Objective-C project type to the new Swift project type.

Considerations when migrating to a Swift Xcode project type

Consider the following before migrating to a Swift Xcode project type:

  • Exporting a project as a Swift Xcode project sets the minimum supported iOS version to 16. This applies even if your project’s target version is lower.
  • Orientation handling during runtime behaves differently when using a Swift Xcode project type. For more information, refer to Manage screen orientation in Swift Xcode projects.
  • When migrating to a Swift Xcode project type, the following functionality isn’t currently available:
    • Unity as a Library
    • Full screen video

Create a Swift Xcode project type

Use the following steps to create a Swift Xcode project type:

  1. Navigate to Edit > Project Settings > Player.
  2. Select the iOS tab.
  3. From Other Settings > Configuration, set Xcode Project Type to Swift. This option is available for both iOS and tvOS.

Migrate post-process scripts for Swift Xcode projects

If you have post-process scripts that modify Xcode project files, you must update them to support changes to the project structure.

Update the project path

The Xcode project file now uses a sanitized version of your Unity project’s name, rather than the static name Unity-iPhone.xcodeproj. To return the correct project path, use the PBXProject.GetPBXProjectPath method.

For example, update your code as follows:

// Before (Objective-C only):
string projPath = Path.Combine(pathToBuiltProject, "Unity-iPhone.xcodeproj/project.pbxproj");

// After (works for both Objective-C and Swift project types):
string projPath = PBXProject.GetPBXProjectPath(pathToBuiltProject);

Review your existing modifications to the .xcodeproj file to ensure they’re still required. For more information, refer to Structure of a Unity Xcode Swift project type.

Identify project types

To identify project types in your post-process scripts, use the UnityEditor.PlayerSettings.xcodeProjectType property. For example:

if (UnityEditor.PlayerSettings.xcodeProjectType == UnityEditor.XcodeProjectType.Swift) {
    // Swift project type specific modifications
} else {
    // Objective-C project type specific modifications
}

Migrate native plug-ins

With the introduction of the Swift project type, you must adapt your native plug-ins to work with the new UnityFramework and the updated Xcode project structure. This migration involves updating API calls, handling lifecycle events differently, and ensuring your plug-ins are correctly configured in the Unity Editor.

Configure plug-in compatibility

Ensure your plug-in is set to be included in the correct Xcode project type. By default, plug-ins are included in both the Objective-C and Swift project types. In the Unity Editor, open the Plugin Inspector for your native plug-in and review its platform settings to confirm the correct compatibility. For more information, refer to Configure a plug-in for iOS with the Inspector window.

Adapt to UnityFramework API changes

The contents of UnityFramework are different when using a Swift Xcode project type. Review your plug-in’s dependencies and update any code that relies on functions or classes that are no longer available.

The UnityPlayer class now provides most of the functionality previously available through UnityAppController.

Note: UnityPlayer isn’t a direct substitute, so it’s recommended to review the Swift project type API reference for details on its specific methods and properties.

// Before:
UnityAppController* appController = GetAppController();

// After (Swift):
let player = UnityPlayer.shared

// After (Objective-C):
UnityPlayer *player = [UnityPlayer shared];

View and ViewController Access

To access the main rendering view and root view controller, use the properties on the UnityPlayer instance.

// Before:
UIView* unityView = GetAppController().unityView;
UIView* unityView = UnityGetUnityView();
UIViewController* rootVC = GetAppController().rootViewController;
UIViewController* rootVC = UnityGetGLViewController();

// After (Swift):
let unityView = UnityPlayer.shared.renderingView
let rootVC = UnityPlayer.shared.rootViewController

// After (Objective-C):
UIView *unityView = [[UnityPlayer shared] renderingView];
UIViewController *rootVC = [[UnityPlayer shared] rootViewController];

Pause and Resume

Pausing and resuming the application is now handled through methods on the UnityPlayer instance. For example:

// Before:
if (!UnityIsPaused()) {
    UnityPause(1);  // pause
}
UnityPause(0);  // resume

// After (Swift):
if (!UnityPlayer.shared.isPaused()) {
    UnityPlayer.shared.pause()
}
UnityPlayer.shared.resume()

// After (Objective-C):
if (![[UnityPlayer shared] isPaused]) {
    [[UnityPlayer shared] pause];
}
[[UnityPlayer shared] resume];

Migrate to NotificationCenter for lifecycle events

If your plug-in previously depended on LifeCycleListener.h or AppDelegateListener, you must migrate to using NotificationCenter to handle lifecycle events. The event definitions are now located in UnityAPI/UnityPluginInterface/UnityNotifications.swift.

// Before (using LifeCycleListener protocol):
@interface MyPlugin : NSObject<AppDelegateListener>
@end
- (void)applicationWillFinishLaunchingWithOptions:(NSNotification*)notification { ... }

// After (Swift):
NotificationCenter.default.addObserver(
    forName: UnityNotifications.applicationWillFinishLaunching,
    object: nil, queue: nil
) { _ in /* handle */ }

// After (Objective-C):
[[NSNotificationCenter defaultCenter]
    addObserverForName:UnityNotifications.applicationWillFinishLaunching
    object:nil queue:nil usingBlock:^(NSNotification *note) { /* handle */ }];

Available notifications include:

  • applicationWillFinishLaunching
  • applicationDidRegisterForRemoteNotifications
  • applicationDidFailToRegisterForRemoteNotifications
  • applicationDidReceiveRemoteNotification
  • unityDidQuit
  • unityDidUnload
  • applicationHandleEventsForBackgroundURLSession
  • sceneOpenURLContexts
  • UIApplication.didBecomeActiveNotification
  • UIApplication.didFinishLaunchingNotification

Note: To prevent duplicate notifications, Unity filters out certain lifecycle and app delegate events that iOS already provides, such as didFinishLaunchingNotification.

Call C# from native code

For the Swift project type, the recommended way to call into C# script is by using the UnityPlayer.sendMessage() method. The UnitySendMessage() C function is still available but now requires you to import UnityPluginInterface.h.

// Before (C/C++/Objective-C):
UnitySendMessage("GameObjectName", "MethodName", "argument");

// After (Swift):
UnityPlayer.shared.sendMessage(toGameObject: "GameObjectName", method: "MethodName", argument: "argument")
UnitySendMessage("GameObjectName", "MethodName", "argument")

// After (Objective-C):
#import "UnityPluginInterface.h"
#import <UnityFramework/UnityFramework-Swift.h>

[[UnityPlayer shared] sendMessageToGameObject:@"GameObjectName" method:@"MethodName" argument:@"argument"];
UnitySendMessage("GameObjectName", "MethodName", "argument");

// C/C++ still works (requires #import "UnityPluginInterface.h"):
UnitySendMessage("GameObjectName", "MethodName", "argument");

Conditional Compilation

If you need to support both Xcode project types within the same plug-in source file, use the UNITY_XCODE_PROJECT_TYPE_SWIFT preprocessor macro to create different code paths.

#ifdef UNITY_XCODE_PROJECT_TYPE_SWIFT
    UnityPlayer *player = [UnityPlayer shared];
#else
    UnityAppController* appController = GetAppController();
#endif

Low level native plug-in API

The low-level native plug-in API remains the same, but the location of the header files has changed. The headers are now located in the UnityAPI/UnityPluginInterface/ directory.

However, you can continue to import them in your code using the same syntax as before.

Introduction to the Swift Xcode project type for iOS and tvOS
Structure of a Unity Xcode Swift project type