ios - AppDelegate.Swift 上的线程处理

标签 ios swift multithreading firebase

我的应用最近因以下原因被 Apple 拒绝:

Exception Type:  EXC_CRASH (SIGKILL)
Exception Codes: 0x0000000000000000, 0x0000000000000000
Exception Note:  EXC_CORPSE_NOTIFY
Termination Reason: Namespace SPRINGBOARD, Code 0x8badf00d
Termination Description: SPRINGBOARD, scene-create watchdog transgression: ********* exhausted real (wall clock) time allowance of 17.77 seconds | ProcessVisibility: Foreground | ProcessState: Running | WatchdogEvent: scene-create | WatchdogVisibility: Foreground | WatchdogCPUStatistics: ( | "Elapsed total CPU time (seconds): 37.550 (user 37.550, system 0.000), 63% CPU", | "Elapsed application CPU time (seconds): 1.015, 2% CPU" | )
Triggered by Thread:  0

下面是我的代码,作为 AppDelegate:

  1. 我是否在主线程中运行了任何可能导致拒绝的代码?我了解拒绝与错误处理有关。

  2. 如果是这样,我如何将相关代码移动到后台线程?

    @UIApplicationMain    class AppDelegate: UIResponder, UIApplicationDelegate {
    
        var window: UIWindow?
    
    
        func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    
            let font = UIFont.systemFont(ofSize: 14)
            let normalAttributes: [NSAttributedString.Key: Any] = [NSAttributedString.Key.font : font, NSAttributedString.Key.foregroundColor: UIColor.white]
            UITabBarItem.appearance().setTitleTextAttributes(normalAttributes, for: .normal)
            let selectedAttributes: [NSAttributedString.Key: Any] = [NSAttributedString.Key.font : font, NSAttributedString.Key.foregroundColor: UIColor.appYellow]
            UITabBarItem.appearance().setTitleTextAttributes(selectedAttributes, for: .selected)
            UITabBar.appearance().unselectedItemTintColor = UIColor.white
    
            GADMobileAds.configure(withApplicationID: "xxxxxx")
    
            TWTRTwitter.sharedInstance().start(withConsumerKey: "xxxxxxxxxxxxxxx", consumerSecret: "xxxxxxxxxxxxxxxxxxx")
    
            FirebaseApp.configure()
    
            let defaults: [String: Any?] = ["bet_interstitial_frequency":       PlaceWagerViewController.DEFAULT_INTERSTITIAL_FREQUENCY,
                                            "event_interstitial_frequency": PlaceWagerViewController.DEFAULT_INTERSTITIAL_FREQUENCY,
                                            "rewarded_video_text": "View Ad",
                                            "scorecard_display_variant": "no_button",
                                            "unlock_icon_2": "coin"]
            RemoteConfig.remoteConfig().setDefaults(defaults as? [String: NSObject])
            RemoteConfig.remoteConfig().fetch(completionHandler: { (status, error) in
                if error == nil {
                    RemoteConfig.remoteConfig().activateFetched()
                }
            })
    
            Messaging.messaging().delegate = self
    
            self.window = UIWindow(frame: UIScreen.main.bounds)
    
            if(Auth.auth().currentUser) == nil {
                openLanding()
            }else {
                openHome()
            }
            return true
        }
    
        func openLanding() {
            let storyboard : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
            let initialViewControlleripad = storyboard.instantiateViewController(withIdentifier: "LandingViewController")
            self.window?.rootViewController = initialViewControlleripad
            self.window?.makeKeyAndVisible()
        }
    
        func openHome() {
            let storyboard : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
            let initialViewControlleripad = storyboard.instantiateViewController(withIdentifier: "HomeTabBarController") as! UITabBarController
            self.window?.rootViewController = initialViewControlleripad
            self.window?.makeKeyAndVisible()
            let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
            UNUserNotificationCenter.current().requestAuthorization(
                options: authOptions,
                completionHandler: {_, _ in })
            UIApplication.shared.registerForRemoteNotifications()
        }
    
        func handleNotification(userInfo: [AnyHashable : Any]) {
            let vc = self.window!.rootViewController!.topMostViewController()
    
            guard let pushType = userInfo["push_type"] as? String else {
                return
            }
            switch pushType {
            case "free_chips", "picks_sold":
                CashierViewController.openCashier(sender: vc)
                break
            case "bet_result":
                let wagerKey = userInfo["wager_id"] as? String ?? ""
                WagerViewController.openWager(sender: vc, wagerKey: wagerKey)
                break
            case "user_profile":
                let userId = userInfo["profile_id"] as? String ?? ""
                ProfileViewController.openPorfile(vc: vc, userId: userId)
                break
            default:
                break
            }
        }
    
    
        func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
            let sourceApplication = options[UIApplication.OpenURLOptionsKey.sourceApplication] as! String?
            if FUIAuth.defaultAuthUI()?.handleOpen(url, sourceApplication: sourceApplication) ?? false {
                return true
            }
            return false
        }
    
    
        func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
    
    
            print(userInfo)
            handleNotification(userInfo: userInfo)
            completionHandler(UIBackgroundFetchResult.newData)
        }
    
    
        func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
            print("Unable to register for remote notifications: \(error.localizedDescription)")
        }
        func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
            print("APNs token retrieved: \(deviceToken)")
    
        }
    
        func handleDynamicLink(_ dynamicLink: DynamicLink) {
            guard let url = dynamicLink.url else {
                return
            }
    
    
            let splitLink = url.absoluteString.replacingOccurrences(of: "https://betshark.app/l/", with: "").split(separator: "/")
    
            if Auth.auth().currentUser != nil {
                let vc = self.window!.rootViewController!.topMostViewController()
                if splitLink[0] == "bet" {
                    WagerViewController.openWager(sender: vc, wagerKey: String(splitLink[1]))
                }
            }
        }
    
        func application(_ application: UIApplication, continue userActivity:
            NSUserActivity, restorationHandler: @escaping
            ([UIUserActivityRestoring]?) -> Void) -> Bool {
            if let incomingURL = userActivity.webpageURL {
                let handledLink =
                    DynamicLinks.dynamicLinks().handleUniversalLink(incomingURL) {
                        (dynamicLink, error) in
                        guard error == nil else {
                            print("dynmaicLink error \(error?.localizedDescription)")
                            return
                        }
    
                        if let dynamicLink = dynamicLink {
                            self.handleDynamicLink(dynamicLink)
                        }
                }
                if handledLink {
                    return true
                }else {
                    return false
                }
            }
            return false
    
        }
    }
    
    
    extension AppDelegate : MessagingDelegate {
        func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) {
            print("Firebase registration token: \(fcmToken)")
    
            let dataDict:[String: String] = ["token": fcmToken]
            NotificationCenter.default.post(name: Notification.Name("FCMToken"), object: nil, userInfo: dataDict)
    
        }
    
        func messaging(_ messaging: Messaging, didReceive remoteMessage: MessagingRemoteMessage) {
            print("Received data message: \(remoteMessage.appData)")
        }
    }
    

最佳答案

Understanding and Analyzing Application Crash Reports告诉我们:

The exception code 0x8badf00d indicates that an application has been terminated by iOS because a watchdog timeout occurred. The application took too long to launch, terminate, or respond to system events. One common cause of this is doing synchronous networking on the main thread. Whatever operation is on Thread 0 needs to be moved to a background thread, or processed differently, so that it does not block the main thread.

“watchdog”引用(和代码,0x8badf00d;“吃了坏食物”哈哈)告诉你有东西阻塞了主线程(在本例中为 17.7 秒)。

您需要确定在此过程(或应用程序启动的其他地方)中的哪些内容可能会阻塞这么长时间。您可以通过识别以上哪些是同步任务来做到这一点。或者您可以使用 Instruments 中的“时间分析器”对此进行经验测试(并且您可能想尝试使用网络链接调节器来模拟非常糟糕的网络条件)。

但我同意这 Firebase issue you identified是一个可能的候选人。

关于ios - AppDelegate.Swift 上的线程处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54559883/

相关文章:

ios - 是否可以使用 sqlcipher 在 iOS 上使用全文搜索?

ios - 如何使用 NSUserDefaults 从不同的 View Controller 更新标签

ios - 无法访问类对象变量

objective-c - 在 iOS 中的多个项目之间共享代码的最佳方式

c# - .NET 中的线程中止

c# - 如何使用 UICollectionViewCompositionalLayout 和多种单元格类型创建自动调整大小的单元格?

ios - 将 Google Cloud Endpoints 用于基于 Swift 语言构建的 iOS 应用

swift - 如何按搜索词过滤短语数组

java - 使用多个 IO 流通过 Java 套接字传输文件

multithreading - System.Linq.Dynamic .Select ("new ...") 似乎不是线程安全的