iOS13适配之SceneDelegte

问题引入

老项目升级到了XCode11 + iOS13,但是通过第三方平台还是收集到了崩溃信息。以这个最为棘手:
崩溃时发生的异常:
在这里插入图片描述
崩溃调用栈:
0 CoreFoundation ___exceptionPreprocess + 220
1 libobjc.A.dylib objc_exception_throw + 56
2 CoreFoundation +[_CFXNotificationTokenRegistration keyCallbacks]
3 Foundation -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 128
4 UIKitCore -[UIApplication _runWithMainScene:transitionContext:completion:] + 1920
5 UIKitCore -[_UISceneLifecycleMultiplexer completeApplicationLaunchWithFBSScene:transitionContext:] + 148
6 UIKitCore _UIScenePerformActionsWithLifecycleActionMask + 100
7 UIKitCore ___101-[_UISceneLifecycleMultiplexer _evalTransitionToSettings:fromSettings:forceExit:withTransitionStore:]_block_invoke + 196
8 UIKitCore -[_UISceneLifecycleMultiplexer _performBlock:withApplicationOfDeactivationReasons:fromReasons:] + 296
9 UIKitCore -[_UISceneLifecycleMultiplexer _evalTransitionToSettings:fromSettings:forceExit:withTransitionStore:] + 736
10 UIKitCore -[_UISceneLifecycleMultiplexer uiScene:transitionedFromState:withTransitionContext:] + 336
11 UIKitCore ___186-[_UIWindowSceneFBSSceneTransitionContextDrivenLifecycleSettingsDiffAction _performActionsForUIScene:withUpdatedFBSScene:settingsDiff:fromSettings:transitionContext:lifecycleActionType:]_block_invoke_2 + 188
12 UIKitCore +[BSAnimationSettings(UIKit) tryAnimatingWithSettings:actions:completion:] + 824
13 UIKitCore _UISceneSettingsDiffActionPerformChangesWithTransitionContext + 244
14 UIKitCore ___186-[_UIWindowSceneFBSSceneTransitionContextDrivenLifecycleSettingsDiffAction _performActionsForUIScene:withUpdatedFBSScene:settingsDiff:fromSettings:transitionContext:lifecycleActionType:]_block_invoke + 136
15 UIKitCore _UISceneSettingsDiffActionPerformActionsWithDelayForTransitionContext + 100
16 UIKitCore -[_UIWindowSceneFBSSceneTransitionContextDrivenLifecycleSettingsDiffAction _performActionsForUIScene:withUpdatedFBSScene:settingsDiff:fromSettings:transitionContext:lifecycleActionType:] + 376
17 UIKitCore ___64-[UIScene scene:didUpdateWithDiff:transitionContext:completion:]_block_invoke + 636
18 UIKitCore -[UIScene _emitSceneSettingsUpdateResponseForCompletion:afterSceneUpdateWork:] + 248
19 UIKitCore -[UIScene scene:didUpdateWithDiff:transitionContext:completion:] + 220
20 UIKitCore -[UIApplication workspace:didCreateScene:withTransitionContext:completion:] + 548
21 UIKitCore -[UIApplicationSceneClientAgent scene:didInitializeWithEvent:completion:] + 360
22 FrontBoardServices -[FBSSceneImpl _callOutQueue_agent_didCreateWithTransitionContext:completion:] + 436
23 FrontBoardServices ___86-[FBSWorkspaceScenesClient sceneID:createWithParameters:transitionContext:completion:]_block_invoke.154 + 100
24 FrontBoardServices -[FBSWorkspace _calloutQueue_executeCalloutFromSource:withBlock:] + 232
25 FrontBoardServices ___86-[FBSWorkspaceScenesClient sceneID:createWithParameters:transitionContext:completion:]_block_invoke + 312
26 libdispatch.dylib __dispatch_client_callout + 16
27 libdispatch.dylib __dispatch_block_invoke_direct V A R I A N T VARIANT armv81 + 216
28 FrontBoardServices _FBSSERIALQUEUE_IS_CALLING_OUT_TO_A_BLOCK + 40
29 FrontBoardServices -[FBSSerialQueue _queue_performNextIfPossible] + 404
30 FrontBoardServices -[FBSSerialQueue _performNextFromRunLoopSource] + 28
31 CoreFoundation _CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION + 24
32 CoreFoundation ___CFRunLoopDoSource0 + 80
33 CoreFoundation ___CFRunLoopDoSources0 + 180
34 CoreFoundation ___CFRunLoopRun + 1080
35 CoreFoundation CFRunLoopRunSpecific + 464
36 GraphicsServices GSEventRunModal + 104
37 UIKitCore UIApplicationMain + 1936
38 Mara main (SocialPhotoRecorderViewController.swift:19)
39 libdyld.dylib _start + 4

分析

  1. 这是个很难看懂的调用栈,因为除了一行自己的代码之外,其他38行都在是系统输出的日志。自己那行代码的输出也完全是“不着调”的。
  2. 搜索“_UISceneLifecycleMultiplexer”确定是在iOS13才出现的,加之出问题的用户的系统都是iOS13,猜测与iOS13的新的UIScene和 UISceneDelegate相关。
  3. 进行CodeReview。发现在AppDelegate的didFinishLaunchingWithOptions方法中确实设定了rootViewController
self.window?.rootViewController = MainTabBarController()

但是在MinTabBarController的第一个子视图A的viewDidLoad方法中进行了创建WIndow对象,并向其添加view的操作

let window = UIWindow()
window.addSubview(view)

推测很可能这里发生了Crash。

解决方案

  1. 所以在现有工程中添加了SceneDelegate.swift,将iOS13上面启动过程移到func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions)方法中。并AppDelegate的将前后台切替方法Copy一份到SceneDelegate中
func applicationDidBecomeActive(_ application: UIApplication) ->
func sceneDidBecomeActive(_ scene: UIScene)
func applicationDidEnterBackground(_ application: UIApplication) ->
func sceneDidEnterBackground(_ scene: UIScene)

来自第三方App的启动:

func application(UIApplication, open: URL, options: [UIApplication.OpenURLOptionsKey : Any]) -> Bool -> 
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>)

有继续一个活动的数据(Handoof数据共享

(https://developer.apple.com/library/archive/documentation/UserExperience/Conceptual/Handoff/HandoffFundamentals/HandoffFundamentals.html#//apple_ref/doc/uid/TP40014338))
func application(UIApplication, continue: NSUserActivity, restorationHandler: ([UIUserActivityRestoring]?) -> Void) -> Bool ->
func scene(_ scene: UIScene, continue userActivity: NSUserActivity)
  1. 修改了iOS13上取得Window的方法
func getAppDelegateWindow() -> UIWindow? {
        var window: UIWindow? = nil
        if #available(iOS 13.0, *) {
            if let scene = UIApplication.shared.connectedScenes.first?.delegate as? SceneDelegate {
                window = scene.window
            }
        } else {
            window = self.window
        }
        return window
    }
  1. 并修改了创建Window的方法
if #available(iOS 13.0, *) {
       let windowScene = UIApplication.shared.connectedScenes.filter { $0.activationState == .foregroundActive }.first
       if let windowScene = windowScene as? UIWindowScene {
           alertWindow = UIWindow(windowScene: windowScene)
           alertWindow.frame = UIScreen.main.bounds
           alertWindow.backgroundColor = .clear
       }
} else {
    let window = UIWindow(frame: UIScreen.main.bounds)
}

参考:
官方:
UIScene
Specifying the Scenes Your App Supports

1,Add a Scene Delegate to your current project
2,app 启动不了 ,停在启动界面 [UIApplication _runWithMainScene:transitionContext:completion:]
3,iOS 13 app crash on start on start - Crash Log
4,关于ios 13使用makeKeyAndVisible无效的问题
5,Understanding UIWindow in iOS

发布了74 篇原创文章 · 获赞 81 · 访问量 12万+

猜你喜欢

转载自blog.csdn.net/dangyalingengjia/article/details/103378476