Documentation

Unity Engine


User Manual

Script Reference

Unity Engine


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.
Read time 5 minutesLast updated 22 days ago

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.renderingViewlet 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.