1

大约每周一次,我会遇到这样的崩溃。也许我错了,但我没有看到我的应用程序(“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

....
4

1 回答 1

3

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

崩溃报告有一个重要的行:“终止原因:命名空间 SPRINGBOARD,代码 0x8badf00d”-> SPRINGBOARD 试图在后台启动应用程序......并且“0x8dadf00d”可以读作“吃了不好的食物”(看看这里StackOverflow,对该代码的大量解释)

该问题的根本原因只是启动时间。在后台开始的时间太长了。后台启动的时间限制约为 5 到 7 秒。在前台启动的允许时间窗口约为 20 秒。

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

要了解如何分析 main() 之前的时间,我建议观看视频“优化应用程序启动时间”,Session 406,WWDC 2016。他们详细解释了在 main() 之前发生了什么以及如何分析和测量它。它们描述了几个产生有用日志的环境变量(在方案的“参数”部分设置)。

“main()”,是的,我是在这次考试中学到的。Swift 允许它有一个 main()。甚至可以在函数、类、结构之外执行语句……在 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”语句。该语句“模拟” main() 函数,因此它是多余的。

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

好的,一如既往:“如果你衡量,你就能管理”。

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

所以我的第一步是通过使用 GCD(Grand Central Dispatch)将尽可能多的工作从主要威胁转移。GCD 非常易于使用,并为您提供了很多选项来微调多个线程的工作负载。WWDC 上有几个关于 GCD 的视频,我个人最喜欢的是“使用 GCD 构建响应式和高效的应用程序”,Session 718,WWDC 2015。

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

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

嗯,神奇的词是“第一屏”。

我喜欢我的 Main.storyboard,它看起来非常漂亮且适应性强。所以我不想把它拆掉。幸运的是,我找到了这个博客http://timdietrich.me/blog/swift-multiple-storyboards/。它描述了在 swift/xcode 项目中使用多个故事板所需的步骤。在互联网上还有其他几个可以找到,但是这个很容易阅读和理解。

所以我创建了一个名为“Start.storyboard”的故事板。这个故事板非常简单,只是 Launchscreen.storyboard 的一个副本。我用它作为“第一个屏幕”。

我为这个开始屏幕的 ViewController 创建了这个类,它除了启动我的 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”更改为“Start”,因为新的初始故事板称为“Start.storyboard”。

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

好的,这就是我摆脱这种崩溃的方式......也许它会帮助其他人......

快乐编码;-)

于 2017-06-05T09:37:19.983 回答