因为现有的崩溃报告器虽然可以报告崩溃,但它们本可以做得更多。以下是 KSCrash 的一些关键特性:
在过去几年里,我的生活发生了很大的变化,我无法继续给予 KSCrash 所需的关爱。
我正在寻找有人帮助我维护这个软件包,确保问题得到处理,合并得到适当的审查,并保持代码质量。请亲自联系我(kstenerud at my gmail address)或在#313中发表评论
https://github.com/kstenerud/KSCrash.git
将以下内容添加到你的 Package.swift
文件中
dependencies: [
.package(url: "https://github.com/kstenerud/KSCrash.git", .upToNextMajor(from: "2.0.0-rc.8"))
]
然后,将 "Installations" 作为目标的依赖项包含进去
targets: [
.target(
name: "YourTarget",
dependencies: [
.product(name: "Installations", package: "KSCrash"),
]),
]
添加到你的 Podfile
pod 'KSCrash', '~> 2.0.0-rc.8'
运行
$ pod install
使用生成的 .xcworkspace
文件。
将以下内容添加到你的 AppDelegate.swift
文件中
对于 Swift Package Manager
import KSCrashInstallations
对于 CocoaPods
import KSCrash
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
let installation = CrashInstallationStandard.shared
installation.url = URL(string: "http://put.your.url.here")!
// Install the crash reporting system
let config = KSCrashConfiguration()
config.monitors = [.machException, .signal]
installation.install(with: config) // set `nil` for default config
// Optional: Add an alert confirmation (recommended for email installation)
installation.addConditionalAlert(
withTitle: "Crash Detected",
message: "The app crashed last time it was launched. Send a crash report?",
yesAnswer: "Sure!",
noAnswer: "No thanks"
)
return true
}
}
let installation = CrashInstallationEmail.shared
installation.recipients = ["some@email.address"] // Specify recipients for email reports
// Optional: Send Apple-style reports instead of JSON
installation.setReportStyle(.apple, useDefaultFilenameFormat: true)
let installation = CrashInstallationConsole.shared
installation.printAppleFormat = true // Print crash reports in Apple format for testing
要发送任何未发送的崩溃报告,请调用
installation.sendAllReports { reports, completed, error in
// Stuff to do when report sending is complete
}
KSCrash 包含两个可选的监视器模块:BootTimeMonitor
和 DiscSpaceMonitor
。默认情况下不包含这些模块,如果需要,必须显式添加。它们包含与隐私相关的 API,需要在使用此信息发送到设备之前向用户显示崩溃报告。
要包含这些模块
使用 CocoaPods
pod 'KSCrash/BootTimeMonitor'
pod 'KSCrash/DiscSpaceMonitor'
使用 SPM,添加到你的目标依赖项
.product(name: "BootTimeMonitor", package: "KSCrash"),
.product(name: "DiscSpaceMonitor", package: "KSCrash"),
如果链接了这些模块,它们会自动运行,无需额外设置。库用户有责任为用户同意实现必要的 UI。
有关更多信息,请参阅 Apple 关于 磁盘空间 API 和 系统启动时间 API 的文档。
KSCrash 有一个可选模块,它提供 C++ 和 Swift 符号的反符号化:DemangleFilter
。此模块包含一个 KSCrash 过滤器 (CrashReportFilterDemangle
),可用于在 sendAllReports
调用期间反符号化崩溃报告中的符号(如果此过滤器已添加到过滤器管道中)。
如果您使用 Installations
API,则会自动使用此模块。 如果您想避免反符号化,可以在 CrashInstallation
实例中将 isDemangleEnabled
设置为 false
。
如果您不使用 Installations
API,您可以手动包含此模块
使用 CocoaPods
pod 'KSCrash/DemangleFilter'
使用 SPM,添加到你的目标依赖项
.product(name: "DemangleFilter", package: "KSCrash"),
如果您需要反符号化 C++ 或 Swift 符号,CrashReportFilterDemangle
类也有一个静态 API 供您自己使用。
KSCrash 现在包含高级内存跟踪功能,以帮助检测和防止内存溢出崩溃。新的 KSCrashAppMemoryTracker
允许您实时监控应用程序的内存使用情况、压力和状态转换。 此功能可以实现主动内存管理,帮助您避免因过度使用内存而导致的系统启动终止。 有关如何在您的应用中实现此功能的更多详细信息,请查看“高级用法”部分。
没错!通常,如果您的应用程序因未捕获的 C++ 异常而终止,您只会得到这个
Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0 libsystem_kernel.dylib 0x9750ea6a 0x974fa000 + 84586 (__pthread_kill + 10)
1 libsystem_sim_c.dylib 0x04d56578 0x4d0f000 + 292216 (abort + 137)
2 libc++abi.dylib 0x04ed6f78 0x4ed4000 + 12152 (abort_message + 102)
3 libc++abi.dylib 0x04ed4a20 0x4ed4000 + 2592 (_ZL17default_terminatev + 29)
4 libobjc.A.dylib 0x013110d0 0x130b000 + 24784 (_ZL15_objc_terminatev + 109)
5 libc++abi.dylib 0x04ed4a60 0x4ed4000 + 2656 (_ZL19safe_handler_callerPFvvE + 8)
6 libc++abi.dylib 0x04ed4ac8 0x4ed4000 + 2760 (_ZSt9terminatev + 18)
7 libc++abi.dylib 0x04ed5c48 0x4ed4000 + 7240 (__cxa_rethrow + 77)
8 libobjc.A.dylib 0x01310fb8 0x130b000 + 24504 (objc_exception_rethrow + 42)
9 CoreFoundation 0x01f2af98 0x1ef9000 + 204696 (CFRunLoopRunSpecific + 360)
...
无法跟踪异常是什么或从哪里抛出的!
现在,使用 KSCrash,您可以获得未捕获的异常类型、描述以及它的抛出位置
Application Specific Information:
*** Terminating app due to uncaught exception 'MyException', reason: 'Something bad happened...'
Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0 Crash-Tester 0x0000ad80 0x1000 + 40320 (-[Crasher throwUncaughtCPPException] + 0)
1 Crash-Tester 0x0000842e 0x1000 + 29742 (__32-[AppDelegate(UI) crashCommands]_block_invoke343 + 78)
2 Crash-Tester 0x00009523 0x1000 + 34083 (-[CommandEntry executeWithViewController:] + 67)
3 Crash-Tester 0x00009c0a 0x1000 + 35850 (-[CommandTVC tableView:didSelectRowAtIndexPath:] + 154)
4 UIKit 0x0016f285 0xb4000 + 766597 (-[UITableView _selectRowAtIndexPath:animated:scrollPosition:notifyDelegate:] + 1194)
5 UIKit 0x0016f4ed 0xb4000 + 767213 (-[UITableView _userSelectRowAtPendingSelectionIndexPath:] + 201)
6 Foundation 0x00b795b3 0xb6e000 + 46515 (__NSFireDelayedPerform + 380)
7 CoreFoundation 0x01f45376 0x1efa000 + 308086 (__CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 22)
8 CoreFoundation 0x01f44e06 0x1efa000 + 306694 (__CFRunLoopDoTimer + 534)
9 CoreFoundation 0x01f2ca82 0x1efa000 + 207490 (__CFRunLoopRun + 1810)
10 CoreFoundation 0x01f2bf44 0x1efa000 + 204612 (CFRunLoopRunSpecific + 276)
...
您现在可以报告您自己的自定义崩溃和堆栈跟踪(想想脚本语言)
- (void) reportUserException:(NSString*) name
reason:(NSString*) reason
lineOfCode:(NSString*) lineOfCode
stackTrace:(NSArray*) stackTrace
terminateProgram:(BOOL) terminateProgram;
有关详细信息,请参阅 KSCrash.h。
以下功能应被视为“不稳定”并且默认禁用
如果可能,您应该阅读以下头文件,以充分了解 KSCrash 具有哪些功能以及如何使用它们
KSCrash 被构建成几个模块,分为公共和私有 API
KSCrashRecording
- 处理崩溃事件记录。KSCrashFilters
- 处理崩溃报告。KSCrashSinks
- 管理报告目的地。KSCrashInstallations
- 为不同的报告场景提供易于使用的设置。KSCrashDiscSpaceMonitor
- 监视可用磁盘空间。KSCrashBootTimeMonitor
- 跟踪设备启动时间。KSCrashDemangleFilter
- 在报告管道中反符号化崩溃中的符号。KSCrashRecordingCore
: 崩溃记录的核心功能。KSCrashReportingCore
: 崩溃报告的核心功能。KSCrashCore
: 核心系统功能逻辑。用户应该与公共 API 模块交互,而私有模块处理内部操作。 可以根据需要包含可选模块以获得额外的功能。
另请参见此处的快速代码之旅 here。
设备端符号化要求最终版本中存在基本符号。 要启用此功能,请转到您的应用程序的构建设置,并将Strip Style设置为Debugging Symbols。 这样做会使您的最终二进制文件大小增加大约 5%,但您会获得设备端符号化。
KSCrash 具有高级功能,在检查实际崩溃报告时非常有用。 有些涉及较小的权衡,因此默认情况下禁用大多数这些功能。
您可以通过设置 KSCrash.h 中的 userInfo 属性来将自定义用户数据存储到下一个崩溃报告中。
KSCrash 能够检测僵尸实例(指向已释放对象的悬空指针)。 它通过记录任何被释放的对象的地址和类来实现这一点。 它将这些值存储在缓存中,并以已释放对象的地址为键。 这意味着您设置的缓存大小越小,发生哈希冲突的可能性就越大,并且您会丢失有关先前已释放对象的信息。
启用僵尸对象跟踪后,KSCrash 还会检测到丢失的 NSException 并打印其内容。 某些类型的内存损坏或堆栈损坏崩溃可能会导致异常过早释放,从而进一步阻碍调试应用程序的工作,因此此功能有时会非常方便。
权衡:以在对象释放中增加非常小的开销以及保留一些内存为代价来跟踪僵尸对象。
警告 警告 警告 警告 警告 警告 警告
此功能不稳定!它可能会误报并使您的应用程序崩溃!
如果您的主线程死锁,您的用户界面将变得无响应,并且用户将不得不手动关闭应用程序(这将没有崩溃报告)。 启用死锁检测后,将设置一个看门狗定时器。 如果有任何东西将主线程保持的时间超过看门狗定时器持续时间,KSCrash 将关闭该应用程序,并为您提供一个堆栈跟踪,显示当时主线程正在做什么。
这很棒,但您必须小心:App 初始化通常发生在主线程上。如果您的初始化代码花费的时间超过了看门狗定时器,您的应用将在启动期间被强制关闭! 如果您启用此功能,您必须确保您的任何正常运行代码都不会占用主线程的时间超过看门狗的值! 同时,您需要将定时器设置为足够低的值,以防止用户变得不耐烦并在看门狗触发之前手动关闭应用!
权衡:死锁检测,但您必须更加小心在主线程上运行的内容!
当应用程序崩溃时,内存中通常存在被堆栈、寄存器甚至异常消息引用的对象和字符串。 启用后,KSCrash 将自省这些内存区域,并将它们的内容存储在崩溃报告中。
您还可以通过在 KSCrash 中设置 doNotIntrospectClasses 属性来指定不应自省的类列表。
如果您想在发生崩溃后进行一些额外的处理(可能向报告添加更多上下文数据),您可以这样做。
但是,您必须确保仅使用异步安全的代码,并且最重要的是永远不要从该方法中调用 Objective-C 代码! 在许多情况下,您可以侥幸这样做,但对于某些类型的崩溃,无视此警告的处理程序代码将导致崩溃处理程序崩溃! 请注意,如果发生这种情况,KSCrash 将检测到它并写入一份完整的报告,但您的自定义处理程序代码可能无法完全运行。
权衡:自定义崩溃处理代码,但您必须小心放入其中的内容!
这会将 KSCrash 本来要打印到控制台的内容,转而写入文件。 我主要使用它来调试 KSCrash 本身,但它可能对其他目的有用,因此我公开了一个 API 用于此目的。
KSCrash 现在包含了高级内存跟踪功能,以帮助检测和防止内存不足崩溃。KSCrashAppMemoryTracker
类监控您 App 的内存使用情况、压力和状态转换。它提供了内存状况的实时更新,允许您动态地响应不同的内存状态(正常、警告、紧急、关键、终端)。通过实现 KSCrashAppMemoryTrackerDelegate
协议,您可以接收关于内存变化的通知,并采取适当的措施来减少内存使用,从而有可能避免系统因内存压力而发起的终止。
使用此功能
let memoryTracker = AppMemoryTracker()
memoryTracker.delegate = self
memoryTracker.start()
在你的代理方法中
func appMemoryTracker(_ tracker: AppMemoryTracker, memory: AppMemory, changed changes: AppMemoryTrackerChangeType) {
if changes.contains(.level) {
// Respond to memory level changes
}
}
此功能帮助你在你的应用中实现主动的内存管理策略。
版权所有 (c) 2012 Karl Stenerud
特此授予任何获得本软件及其相关文档文件(“软件”)副本的人员免费许可,以不受限制地处理本软件,包括但不限于使用、复制、修改、合并、出版、分发、再许可和/或销售软件副本的权利,并允许向其提供本软件的人员这样做,但须符合以下条件
上述版权声明和本许可声明应包含在任何重新分发模板文件本身的文件中(但不包含在使用模板构建的项目中)。
本软件按“原样”提供,不提供任何形式的明示或暗示的保证,包括但不限于适销性、特定用途适用性和不侵权的保证。 在任何情况下,作者或版权持有人均不对任何索赔、损害或其他责任负责,无论是在合同、侵权行为或其他方面,由软件或软件的使用或其他处理引起的或与之相关的。