How to port workaround for iOS crash on 15.7? (SKStoreProductViewController sceneDisconnected)

We are observing lots of crashes on iOS 15.7 for our iOS game. Something iOS is responsible for, which is fixed in iOS 16.

More info: [SKStoreProductViewController scen… | Apple Developer Forums

People have suggested workarounds for this problem, But can anyone help me migrate this to Unity?
I really prefer this to be done from inside Unity, and not after exporting the Xcode project and modifying manually; Either by doing something in IPostprocessBuildWithReport, or any other possible way.
(though how to do it manually is also needed, if this can’t be automated)

Available workarounds:
storekit - SKStoreProductViewController crashes for unrecognized selector named sceneDisconnected: in iOS 15.6 beta5 - Stack Overflow, storekit - SKStoreProductViewController crashes for unrecognized selector named sceneDisconnected: in iOS 15.6 beta5 - Stack Overflow

1 Like

Can anyone help with this?

1 Like

OK, I had to do it myself.

Call this method from an IPostprocessBuildWithReport in OnPostprocessBuild() and pass it report.summary.outputPath and all will be set:

//Fix for a bug that Apple introduced in iOS 15.7 that leads to crashes
    //More info: https://developer.apple.com/forums/thread/714464 , workarounds: https://stackoverflow.com/a/73796906/1235063 , https://stackoverflow.com/questions/72907240/skstoreproductviewcontroller-crashes-for-unrecognized-selector-named-scenediscon/74232140#74232140
    //Expections on Xcode project:
    //SWIFT_OBJC_BRIDGING_HEADER must be set (only for Unity-iPhone target)
    //CLANG_ENABLE_MODULES set to true, for Unity-iPhone, Unity-iPhone Tests, and UnityFramework
    //SWIFT_VERSION for the 3 targets must be specified
    private void AddWorkaroundForCrashIniOS15_7(string pathToBuiltProject)
    {
        string projectPath = PBXProject.GetPBXProjectPath(pathToBuiltProject);
        PBXProject project = new PBXProject();
        project.ReadFromString(File.ReadAllText(projectPath));

        string swiftFileName = "CrashPrevIOS15_7.swift";
        string swiftFileContent = "//\n//  File.swift\n//  Unity-iPhone\n//\n//  Created by Paiman Roointan on 1/18/23.\n//\n\nimport Foundation\nimport StoreKit\n\n@available(iOS, introduced: 15.7, obsoleted: 16.0)\n@objc extension SKStoreProductViewController {\n    func sceneDisconnected(_ arg: AnyObject) {}\n    func appWillTerminate() {}\n}\n";
        string swiftFilePath = Path.Combine(pathToBuiltProject, swiftFileName);

        if (!File.Exists(swiftFilePath))
            File.WriteAllText(swiftFilePath, swiftFileContent);

        project.AddFileToBuild(
                    project.GetUnityMainTargetGuid(),
                    project.AddFile(swiftFileName, swiftFileName));

        string bridgingHeaderFileName = "Unity-iPhone-Bridging-Header.h";
        string bridgingHeaderFileContent = "//\n//  Use this file to import your target's public headers that you would like to expose to Swift.\n//";
        string bridgingHeaderFilePath = Path.Combine(pathToBuiltProject, bridgingHeaderFileName);

        if (!File.Exists(bridgingHeaderFilePath))
            File.WriteAllText(bridgingHeaderFilePath, bridgingHeaderFileContent);

        if (string.IsNullOrEmpty(project.GetBuildPropertyForConfig(project.GetUnityMainTargetGuid(), "SWIFT_VERSION")))
            project.SetBuildProperty(project.GetUnityMainTargetGuid(), "SWIFT_VERSION", "5.0");

        if (string.IsNullOrEmpty(project.GetBuildPropertyForConfig(project.GetUnityFrameworkTargetGuid(), "SWIFT_VERSION")))
            project.SetBuildProperty(project.GetUnityFrameworkTargetGuid(), "SWIFT_VERSION", "5.0");

        if (string.IsNullOrEmpty(project.GetBuildPropertyForConfig(project.TargetGuidByName("Unity-iPhone Tests"), "SWIFT_VERSION")))
            project.SetBuildProperty(project.TargetGuidByName("Unity-iPhone Tests"), "SWIFT_VERSION", "5.0");

        project.SetBuildProperty(project.GetUnityMainTargetGuid(), "CLANG_ENABLE_MODULES", "YES");
        project.SetBuildProperty(project.GetUnityFrameworkTargetGuid(), "CLANG_ENABLE_MODULES", "YES");
        project.SetBuildProperty(project.TargetGuidByName("Unity-iPhone Tests"), "CLANG_ENABLE_MODULES", "YES");

        project.SetBuildProperty(project.GetUnityMainTargetGuid(), "SWIFT_OBJC_BRIDGING_HEADER", bridgingHeaderFileName);

        File.WriteAllText(projectPath, project.WriteToString());
2 Likes