我的应用最近因以下原因而被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:
我是否在主线程中运行任何可能导致拒绝的代码?我了解拒绝与错误处理有关。
如果是,我如何将相关代码移至后台线程?
@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)")
}
}
答案 0 :(得分:1)
Understanding and Analyzing Application Crash Reports告诉我们:
异常代码
0x8badf00d
表示应用程序已被iOS终止,因为发生了看门狗超时。该应用程序启动,终止或响应系统事件所需的时间过长。一个常见的原因是在主线程上进行同步网络连接。线程0上的任何操作都需要移至后台线程,或进行不同的处理,以免阻塞主线程。
“看门狗”参考(和代码0x8badf00d
;“吃不好的食物”大声笑)告诉您,您有东西在阻塞主线程(在本示例中为17.7秒)。
您需要确定在此过程中(或应用程序启动的其他地方)可能会阻止该时间的时间。您可以通过识别以上哪些是同步任务来执行此操作。或者,您可以使用Instruments中的“时间分析器”进行经验测试(并且您可能希望尝试使用网络链接调节器来模拟真正糟糕的网络条件)。
但是我同意这个Firebase issue you identified是可能的候选人。