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:
- Navigate to Edit > > Player.Project Settings
?
- Select the iOS tab.
- 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 . To return the correct project path, use the method.
Unity-iPhone.xcodeprojPBXProject.GetPBXProjectPathFor 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 file to ensure they're still required. For more information, refer to Structure of a Unity Xcode Swift project type.
.xcodeprojIdentify project types
To identify project types in your post-process scripts, use the property. For example:
UnityEditor.PlayerSettings.xcodeProjectTypeif (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 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.
UnityFrameworkThe class now provides most of the functionality previously available through .
UnityPlayerUnityAppController// 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 instance.
UnityPlayer// 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 instance. For example:
UnityPlayer// 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 or , you must migrate to using to handle lifecycle events. The event definitions are now located in .
LifeCycleListener.hAppDelegateListenerNotificationCenterUnityAPI/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:
applicationWillFinishLaunchingapplicationDidRegisterForRemoteNotificationsapplicationDidFailToRegisterForRemoteNotificationsapplicationDidReceiveRemoteNotificationunityDidQuitunityDidUnloadapplicationHandleEventsForBackgroundURLSessionsceneOpenURLContextsUIApplication.didBecomeActiveNotificationUIApplication.didFinishLaunchingNotification
Call C# from native code
For the Swift project type, the recommended way to call into C# script is by using the method. The C function is still available but now requires you to import .
UnityPlayer.sendMessage()UnitySendMessage()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 preprocessor macro to create different code paths.
UNITY_XCODE_PROJECT_TYPE_SWIFT#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 directory.
UnityAPI/UnityPluginInterface/However, you can continue to import them in your code using the same syntax as before.