Ios AppDelegate.Swift上的线程处理
我的应用程序最近因以下原因被苹果拒绝:Ios AppDelegate.Swift上的线程处理,ios,swift,multithreading,firebase,Ios,Swift,Multithreading,Firebase,我的应用程序最近因以下原因被苹果拒绝: Exception Type: EXC_CRASH (SIGKILL) Exception Codes: 0x0000000000000000, 0x0000000000000000 Exception Note: EXC_CORPSE_NOTIFY Termination Reason: Namespace SPRINGBOARD, Code 0x8badf00d Termination Description: SPRINGBOARD, scene
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的代码:
@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)")
}
}
0x8badf00d
表示由于出现看门狗超时,应用程序已被iOS终止。应用程序启动、终止或响应系统事件花费的时间太长。一个常见的原因是在主线程上进行同步联网。线程0上的任何操作都需要移动到后台线程,或者进行不同的处理,以便它不会阻塞主线程
“watchdog”引用(以及代码,0x8badf00d
;“吃坏了的食物”lol)告诉您有东西阻塞了主线程(在本例中为17.7秒)
您需要确定在这个过程中(或在您启动应用程序的其他地方)可能会阻止哪些内容这么长时间。您可以通过识别上面哪些是同步任务来实现这一点。或者,您可以使用仪器中的“时间分析器”进行经验测试(您可能希望尝试使用网络链接调节器来模拟非常糟糕的网络条件)
但我同意这是一个很可能的候选者。谢谢,但我相信是Firebase bug导致了它。我只是想确保上面的内容没有在主线程上运行。明白了吗?所以它确实需要移动到后台,否则它将继续导致看门狗错误?就我个人而言,我不会把所有这些都放到后台线程中,而是缩小它的范围以找到违规者。我怀疑一个普通的Firebase bug(因为我们很多人使用它时不会发生意外)。不过,我不熟悉您正在使用的其他一些框架/类。我们已经更新到新的FirebaseUI版本,但是这可能是一个问题,这可能是导致问题的原因简单地将上述代码移动到后台线程作为保护措施有什么危害?您必须确保推送到后台线程的所有内容都是线程安全的,不受竞争条件的影响,等等。别误会我的意思,它可能会工作,但你不知道是否会引入其他问题……明白了-我倾向于相信它是Firebase,因为我已经通过xCode和testFlight进行了测试。我想我唯一的选择之一就是重新提交给苹果公司。我想说的是,糟糕的网络状况是表现这类问题的常见方式(我打赌这就是苹果公司表现出来的方式)。考虑到苹果需要花多长时间来审查这些东西,也许值得花30分钟来消除这种可能性。(如果你不使用这种“网络链接调节器”,你真的应该,无论如何,因为美国开发者经常在理想配置下测试我们的应用程序,而忘记了在模拟真实世界条件下测试我们的应用程序。)