定期 IOS 崩溃,但我没有看到我的应用程序参与崩溃报告

periodic IOS crash, but I do not see any involvement of my app in crash report

我大约每周遇到一次这样的崩溃。也许我错了,但我没有看到我的应用程序有任何参与 ("WayAndSee")。有人知道如何进行吗?

附上崩溃报告(这种崩溃非常典型),我只是截断了库的尾随列表。

非常感谢...

Incident Identifier: 348BDC52-6574-4EED-A6C7-45E79E696875
CrashReporter Key:   f8ac3e1a61b8129920a4ad40aaa56d5536e2ce22
Hardware Model:      iPhone6,2
Process:             WayAndSee [8286]
Path:                /private/var/containers/Bundle/Application/F1542EC3-3708-4B6E-80EA-A2333883359E/WayAndSee.app/WayAndSee
Identifier:          Hobrink.WayAndSee
Version:             2487 (0.3.0)
Code Type:           ARM (Native)
Role:                Foreground
Parent Process:      launchd [1]
Coalition:           Hobrink.WayAndSee [2936]


Date/Time:           2017-04-04 14:28:15.3459 +0200
Launch Time:         2017-04-04 13:05:54.5835 +0200
OS Version:          iPhone OS 10.2.1 (14D27)
Report Version:      104

Exception Type:  EXC_CRASH (SIGKILL)
Exception Codes: 0x0000000000000000, 0x0000000000000000
Exception Note:  EXC_CORPSE_NOTIFY
Termination Reason: Namespace SPRINGBOARD, Code 0x8badf00d
Triggered by Thread:  0

Filtered syslog:
None found

Thread 0 Crashed:
0   libsystem_kernel.dylib          0x1cedf84c mach_msg_trap + 20
1   CoreFoundation                  0x1d7082f9 __CFRunLoopServiceMachPort + 137
2   CoreFoundation                  0x1d7065f7 __CFRunLoopRun + 1015
3   CoreFoundation                  0x1d655533 CFRunLoopRunSpecific + 487
4   CoreFoundation                  0x1d655341 CFRunLoopRunInMode + 105
5   GraphicsServices                0x1ee2cbfd GSEventRunModal + 157
6   UIKit                           0x22863e67 -[UIApplication _run] + 575
7   UIKit                           0x2285e591 UIApplicationMain + 151
8   WayAndSee                       0x000ba890 main (AppDelegateV2a.swift:667)
9   libdyld.dylib                   0x1ce1f50b start + 3

Thread 1 name:  com.apple.uikit.eventfetch-thread
Thread 1:
0   libsystem_kernel.dylib          0x1cedf84c mach_msg_trap + 20
1   CoreFoundation                  0x1d7082f9 __CFRunLoopServiceMachPort + 137
2   CoreFoundation                  0x1d7065f7 __CFRunLoopRun + 1015
3.  CoreFoundation                  0x1d655533 CFRunLoopRunSpecific + 487
4   CoreFoundation                  0x1d655341 CFRunLoopRunInMode + 105
5   Foundation                      0x1dfaf88b -[NSRunLoop(NSRunLoop) runMode:beforeDate:] + 261
6   Foundation                      0x1dfce631 -[NSRunLoop(NSRunLoop) runUntilDate:] + 87
7   UIKit                           0x2316a2b3 -[UIEventFetcher threadMain] + 129
8   Foundation                      0x1e098b11 __NSThread__start__ + 1161
9   libsystem_pthread.dylib         0x1cfa9a27 _pthread_body + 217
10  libsystem_pthread.dylib         0x1cfa994d _pthread_start + 235
11  libsystem_pthread.dylib         0x1cfa749c thread_start + 8

Thread 2 name:  NetworkLoad
Thread 2:
0   libsystem_kernel.dylib          0x1cedf84c mach_msg_trap + 20
1   CoreFoundation                  0x1d7082f9 __CFRunLoopServiceMachPort + 137
2   CoreFoundation                  0x1d7065f7 __CFRunLoopRun + 1015
3   CoreFoundation                  0x1d655533 CFRunLoopRunSpecific + 487
4   CoreFoundation                  0x1d655341 CFRunLoopRunInMode + 105
5   GeoServices                     0x244775ff _runNetworkThread + 475
6   libsystem_pthread.dylib         0x1cfa9a27 _pthread_body + 217
7   libsystem_pthread.dylib         0x1cfa994d _pthread_start + 235
8   libsystem_pthread.dylib         0x1cfa749c thread_start + 8

Thread 3:
0   libsystem_kernel.dylib          0x1cef5744 __workq_kernreturn + 8
1   libsystem_pthread.dylib         0x1cfa7490 start_wqthread + 8

Thread 4:
0   libsystem_pthread.dylib         0x1cfa7488 start_wqthread + 0

Thread 5:
0   libsystem_pthread.dylib         0x1cfa7488 start_wqthread + 0

Thread 6:
0   libsystem_pthread.dylib         0x1cfa7488 start_wqthread + 0

Thread 0 crashed with ARM Thread State (32-bit):
    r0: 0x10004005    r1: 0x07000806      r2: 0x00000000      r3: 0x00000c00
    r4: 0x00002403    r5: 0xffffffff      r6: 0x00000000      r7: 0x0042adb4
    r8: 0x00000c00    r9: 0x00002403     r10: 0x07000806     r11: 0x00000000
    ip: 0xffffffe1    sp: 0x0042ad78      lr: 0x1cedf63f      pc: 0x1cedf84c
  cpsr: 0x60000010

Binary Images:
0xb0000 - 0x177fff WayAndSee armv7  <7506039ae577329ab9868e3122d84f5f> /var/containers/Bundle/Application/F1542EC3-3708-4B6E-80EA-A2333883359E/WayAndSee.app/WayAndSee
0x25c000 - 0x267fff libswiftCoreData.dylib armv7s  <3022e21a184d3e6c93bac1ad7b18be30> /var/containers/Bundle/Application/F1542EC3-3708-4B6E-80EA-A2333883359E/WayAndSee.app/Frameworks/libswiftCoreData.dylib
0x27c000 - 0x28bfff libswiftCoreGraphics.dylib armv7s  <4415e467b6df386591e646e7a2978da6> /var/containers/Bundle/Application/F1542EC3-3708-4B6E-80EA-A2333883359E/WayAndSee.app/Frameworks/libswiftCoreGraphics.dylib
0x2a8000 - 0x2affff libswiftCoreImage.dylib armv7s  <9bbbe5b77fdd3551921ca7ec1a98ae38> /var/containers/Bundle/Application/F1542EC3-3708-4B6E-80EA-A2333883359E/WayAndSee.app/Frameworks/libswiftCoreImage.dylib
0x2c0000 - 0x2ebfff dyld armv7s  <898b6b42ae3b3ffb8de9a96b7071f49d> /usr/lib/dyld
0x42c000 - 0x6abfff libswiftCore.dylib armv7s  <b760608c5d35390099731eedb8821bc0> /var/containers/Bundle/Application/F1542EC3-3708-4B6E-80EA-A2333883359E/WayAndSee.app/Frameworks/libswiftCore.dylib

....

因为我有几个关于我在这个问题上的进展的问题,我决定自己写一个答案。也许这对其他人有帮助。

崩溃报告有一个重要的行:"Termination Reason: Namespace SPRINGBOARD, Code 0x8badf00d" -> SPRINGBOARD 试图在后台启动应用程序...并且“0x8dadf00d”可以读作 "ate bad food"(在此处查看Whosebug,对该代码的大量解释)

该问题的根本原因仅仅是启动时间。后台启动时间太长。后台启动有大约 5 到 7 秒的时间限制。在前台启动的允许时间 window 约为 20 秒。

此时间限制包括 main() 之前和 main() 之后直到应用程序稳定并准备好接收启动事件的时间。应用程序在后台的每次启动都是由启动事件(位置、文件传输等)引起的

要了解如何分析 main() 之前的时间,我建议观看视频 "Optimizing App Startup Time"、Session 406、WWDC 2016。他们详细解释了 main 之前发生的事情以及如何进行对其进行分析和测量。他们描述了几个产生有用日志的环境变量(在方案的 "arguments" 部分中设置)。

"main()",是的,我在这次考试中学会了。 Swift 允许它有一个 main()。甚至可以在函数外执行语句,class,结构......在 swift 中没有真正的需要。但是因为我想测量 main 之后的启动时间,所​​以我写了这个简单的 main.swift 文件来这样做。

//
//  main.swift
//  ...
//
//  Created by Hartwig Hopfenzitz on 31.05.17.
//  Copyright © 2017 Hopfenzitz. All rights reserved.
//

import Foundation
import UIKit

// very first statement after load.. the current time
let WaysStartTime = CFAbsoluteTimeGetCurrent()

// build the parameters for the call to UIApplicationMain()
let argc = CommandLine.argc
let argv = UnsafeMutableRawPointer(CommandLine.unsafeArgv).bindMemory(to: UnsafeMutablePointer<Int8>.self, capacity: Int(CommandLine.argc))

// start the main loop
UIApplicationMain(argc, argv, nil, NSStringFromClass(AppDelegate.self))

如您所见:在第一个陈述中,我花时间。有了这个,我可以测量到应用程序启动时间和 运行.

的时间差

但是:如果您想在 swift 项目中使用 main(),则必须注释掉或删除 AppDelegate.swift 中的语句“@UIApplicationMain”。这个语句 "simulates" main() 函数,所以它会是多余的。

是的,值得在 main() 上开始测量。我还测试了从 "willFinishLaunchingWithOptions:" 开始的时间测量。在我常用的测试设备上,一个 iPhone 5s(真正的测试设备,而不是模拟器),差异大约是 0.4 秒。我确定时间取决于应用程序及其结构,因此我建议从 main() 开始测量它。

好的,一如既往:"if you measure, you are able to manage"。

启动时间慢的常见根本原因是主线程过载。这个主线程是每个应用程序最重要的工作马。它加重了事件循环和 UI 的负担。

所以我的第一步是通过使用 GCD(Grand Central Dispatch)将尽可能多的工作从主要威胁转移开。 GCD 非常易于使用,并为您提供了很多选项来微调多个线程的工作负载。 WWDC 上有很多关于 GCD 的视频,我个人最喜欢的是 "Building Responsive and Efficient Apps with GCD", Session 718, WWDC 2015.

然而,通过这个我大大减少了崩溃的次数,但是......仍然有崩溃......

我的初始屏幕非常复杂,使用了很多自动布局和自动调整大小等。有时在时间限制使应用程序崩溃之前完成渲染需要很长时间。如果我理解正确,IOS 想要启动第一个屏幕并 运行,以考虑成功启动。

嗯,魔法词是 "the first screen"。

我爱我的 Main.storyboard,非常漂亮,适应性强。所以我不想剥离它。幸运的是我找到了这个博客http://timdietrich.me/blog/swift-multiple-storyboards/。它描述了在 swift/xcode 项目中使用多个故事板的必要步骤。在 Internet 上可以找到其他几个,但这一个非常容易阅读和理解。

所以我创建了一个名为 "Start.storyboard" 的故事板。这个故事板很简单,只是复制了Launchscreen.storyboard。我用它作为 "the first screen".

我为这个开始屏幕的 ViewController 创建了这个 class,除了启动我的 Main.Storyboard。

//
//  StartViewController.swift
//  ...
//
//  Created by Hartwig Hopfenzitz on 02.06.17.
//  Copyright © 2017 Hopfenzitz. All rights reserved.
//

import UIKit

class StartViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.

        // Create instance of our main storyboard
        let mainStoryboard = UIStoryboard(name: "Main", bundle: nil)

        // Create the instance of main's initial view controller.
        let mainController = mainStoryboard.instantiateViewController(withIdentifier: "WaysViewController") as UIViewController

        // Make sure it will start on the main thread
        DispatchQueue.main.async(execute: {

            // present it .. and never come back
            mainController.modalTransitionStyle = UIModalTransitionStyle.crossDissolve
            mainController.modalPresentationStyle = .fullScreen // Display on top of current UIView

            self.present(mainController, animated: true, completion: nil)
        })
    }
}

在 Info.plist 中,您将找到密钥 "Main storyboard file base name"。此键告诉哪个故事板是具有初始屏幕的故事板。因此,在我的示例中,您必须将值从 "Main" 更改为 "Start",因为新的初始故事板称为 "Start.storyboard"。

瞧瞧:第一个屏幕几乎立即启动,IOS 对启动时间非常满意。用户不认识。

好的,这就是我摆脱崩溃的方法...也许它会对其他人有所帮助...

编码愉快 ;-)