App Center iOS (崩溃)
App Center崩溃时,每次应用崩溃时,都会自动生成崩溃日志。 日志首先写入设备的存储,当用户再次启动应用时,崩溃报告将发送到App Center。 收集崩溃适用于 beta 版和实时应用,即提交到 App Store。 故障日志包含有助于修复故障的有用信息。
如果 入门 尚未在应用程序中设置 SDK,请遵循以下部分。
此外,iOS 上的崩溃日志需要符号化,请查看App Center 诊断 文档,其中介绍了如何为应用提供符号。
备注
如果附加到调试器,SDK 不会转发任何崩溃日志。 请确保在使应用崩溃时未附加调试器。
备注
若要接收正确符号化的堆栈跟踪,请确保禁用位码。 可以在 iOS 符号App Center中详细了解 位码。
备注
在 4.0.0 版本App Center引入了中断性变更。 按照 迁移到 App Center SDK 4.0.0 及更高版本 部分从App Center迁移。
扩展中的崩溃报告
App Center iOS 扩展中支持崩溃报告。 用法与容器应用程序中的用法相同。
生成测试崩溃
App Center 崩溃将为你提供一个 API,用于生成测试崩溃以便轻松测试 SDK。 此 API 只能在测试/测试版应用中使用,不会在生产应用中执行任何操作。
[MSACCrashes generateTestCrash];
Crashes.generateTestCrash()
获取有关以前的故障的详细信息
App Center 崩溃具有两个 Api,可提供有关应用崩溃情况的详细信息。
应用是否在上一个会话中收到内存不足警告?
在启动 SDK 之后的任何时候,你都可以在上一个会话中检查应用是否收到内存警告:
[MSACCrashes hasReceivedMemoryWarningInLastSession];
Crashes.hasReceivedMemoryWarningInLastSession
备注
此方法只能在启动后使用 Crashes ,它将始终返回 NO 或 false 在启动之前。
备注
在某些情况下,内存不足的设备不能发送事件。
应用在上一个会话中是否崩溃?
启动 SDK 之后,可以随时检查应用是否在上一次启动时崩溃:
[MSACCrashes hasCrashedInLastSession];
Crashes.hasCrashedInLastSession
如果你想要在发生崩溃后调整应用的行为或 UI,这会很方便。
备注
此方法只能在启动后使用 MSACCrashes ,它将始终返回 NO 或 false 在启动之前。
有关最后一个崩溃的详细信息
如果你的应用此前崩溃,你可以获取有关最后一个崩溃的详细信息。
MSACErrorReport *crashReport = [MSACCrashes lastSessionCrashReport];
var crashReport = Crashes.lastSessionCrashReport
备注
此方法只能在启动后使用 Crashes ,它将始终 nil 在开始之前返回。
此 API 有很多用例,最常见的用例是调用此 API 并实现其自定义 CrashesDelegate的人。
自定义 App Center 崩溃的使用情况
App Center 崩溃为开发人员提供回调,以便在向 App Center 发送崩溃日志之前和时执行其他操作。
若要添加自定义行为,需要采用 CrashesDelegate -协议,其所有方法都是可选的。
注册为委托
[MSACCrashes setDelegate:self];
Crashes.delegate = self
备注
您必须在调用 之前 设置委托 AppCenter.start ,因为 App Center 在启动后立即开始处理崩溃。
是否应处理崩溃?
crashes:shouldProcessErrorReport: CrashesDelegate 如果要确定是否需要处理特定的崩溃,请在类中实现-方法(采用-协议)。 例如,可能存在要忽略的系统级崩溃,并且不希望发送到 App Center。
- (BOOL)crashes:(MSACCrashes *)crashes shouldProcessErrorReport:(MSACErrorReport *)errorReport {
return YES; // return YES if the crash report should be processed, otherwise NO.
}
func crashes(_ crashes: Crashes, shouldProcess errorReport: ErrorReport) -> Bool {
return true; // return true if the crash report should be processed, otherwise false.
}
处理的错误
App Center 还允许通过使用处理的异常通过方法跟踪错误 trackError 。 应用可以选择将属性或/和附件附加到已处理的错误报告,以提供更多上下文。
@try {
// Throw error.
} @catch (NSError *error) {
// Init attachments.
NSArray<MSACErrorAttachmentLog *> attachments = @[ MSACErrorAttachmentLog attachmentWithText:@"Hello world!" filename:@"hello.txt"] ]
// Init properties.
NSDictionary *properties = @{ "Category" : "Music", "Wifi" : "On" };
// Track errors.
[MSACCrashes trackError:error withProperties:properties attachments:attachments];
[MSACCrashes trackError:error withProperties:properties attachments:nil];
[MSACCrashes trackError:error withProperties:nil attachments:attachments];
[MSACCrashes trackError:error withProperties:nil attachments:nil];
}
do {
// Throw error.
} catch {
// Init attachments.
let attachments = [ErrorAttachmentLog.attachment(withText: "Hello world!", filename: "hello.txt")]
// Init properties.
let properties:Dictionary<String, String> = ["Category" : "Music", "Wifi" : "On"]
// Track errors.
Crashes.trackError(error, properties: properties, attachments: attachments)
Crashes.trackError(error, properties: properties, attachments: nil)
Crashes.trackError(error, properties: nil, attachments: attachments)
Crashes.trackError(error, properties: nil, attachments: nil)
}
若要跟踪异常,可以使用 trackException 方法:
@try {
// Throw exceptions.
} @catch (NSException *exception) {
// Init exceptions.
MSACExceptionModel *customException1 = [MSACExceptionModel initWithType:@"Custom exception" exceptionMessage:"Track custom exception.", stackTrace:exception.callStackSymbols];
MSACExceptionModel *customException2 = [MSACExceptionModel initWithException:exception];
// Track exceptions.
[MSACCrashes trackException:customException1 withProperties:properties attachments:nil];
[MSACCrashes trackException:customException2 withProperties:properties attachments:nil];
}
do {
// Throw exception.
} catch {
// Init exception.
let exception = ExceptionModel(withType: "Custom exception", exceptionMessage: "Track custom exception.", stackTrace: Thread.callStackSymbols)
// Track exception.
Crashes.trackException(exception, properties: properties, attachments: nil)
}
要求用户同意发送崩溃日志
如果用户隐私对你很重要,你可能想要在将故障报告发送到 App Center 之前获得用户确认。 SDK 公开了一个回调,该回调指示在发送任何崩溃报告之前,App Center 崩溃等待用户确认。
如果你选择执行此操作,则需负责获取用户的确认,例如通过对话框提示获取以下选项之一: " 始终发送"、" 发送" 和 " 不发送"。 基于输入,你会告诉 App Center 崩溃要执行的操作,然后将相应地处理崩溃。
备注
SDK 不显示此对话框,应用必须提供自己的 UI 来要求用户同意。
备注
notifyWithUserConfirmation如果应用未实现用户确认对话框,则该应用不应显式调用; 崩溃模块将隐式处理发送日志。
下面的方法演示如何设置用户确认处理程序:
[MSACCrashes setUserConfirmationHandler:(^(NSArray<MSACErrorReport *> *errorReports) {
// Your code to present your UI to the user, e.g. an UIAlertController.
UIAlertController *alertController = [UIAlertController
alertControllerWithTitle:@"Sorry about that!"
message:@"Do you want to send an anonymous crash report so we can fix the issue?"
preferredStyle:UIAlertControllerStyleAlert];
[alertController
addAction:[UIAlertAction actionWithTitle:@"Don't send"
style:UIAlertActionStyleCancel
handler:^(UIAlertAction *action) {
[MSACCrashes notifyWithUserConfirmation:MSACUserConfirmationDontSend];
}]];
[alertController
addAction:[UIAlertAction actionWithTitle:@"Send"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction *action) {
[MSACCrashes notifyWithUserConfirmation:MSACUserConfirmationSend];
}]];
[alertController
addAction:[UIAlertAction actionWithTitle:@"Always send"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction *action) {
[MSACCrashes notifyWithUserConfirmation:MSACUserConfirmationAlways];
}]];
// Show the alert controller.
[self.window.rootViewController presentViewController:alertController animated:YES completion:nil];
return YES; // Return YES if the SDK should await user confirmation, otherwise NO.
})];
Crashes.setUserConfirmationHandler({ (errorReports: [ErrorReport]) in
// Your code to present your UI to the user, e.g. an UIAlertController.
let alertController = UIAlertController(title: "Sorry about that!",
message: "Do you want to send an anonymous crash report so we can fix the issue?",
preferredStyle:.alert)
alertController.addAction(UIAlertAction(title: "Don't send", style: .cancel) {_ in
Crashes.notify(with: .dontSend)
})
alertController.addAction(UIAlertAction(title: "Send", style: .default) {_ in
Crashes.notify(with: .send)
})
alertController.addAction(UIAlertAction(title: "Always send", style: .default) {_ in
Crashes.notify(with: .always)
})
// Show the alert controller.
self.window?.rootViewController?.present(alertController, animated: true)
return true // Return true if the SDK should await user confirmation, otherwise return false.
})
如果你在 YES / true 上述处理程序块中返回,你的应用程序应使用以下 API 获取用户权限并向 SDK 发送包含结果的消息。 如果对此使用警报,请与上述示例中所述的一样,在回调的实现中调用它 alertView:clickedButtonAtIndex: 。
// Depending on the users's choice, call notifyWithUserConfirmation: with the right value.
[MSACCrashes notifyWithUserConfirmation:MSACUserConfirmationDontSend];
[MSACCrashes notifyWithUserConfirmation:MSACUserConfirmationSend];
[MSACCrashes notifyWithUserConfirmation:MSACUserConfirmationAlways];
// Depending on the user's choice, call notify(with:) with the right value.
Crashes.notify(with: .dontSend)
Crashes.notify(with: .send)
Crashes.notify(with: .always)
获取有关故障日志发送状态的信息
有时,你想要了解应用崩溃的状态。 常见用例是,你可能想要显示 UI 来告知用户应用正在提交崩溃报告,或者,如果应用在启动后快速崩溃,则你需要调整应用的行为以确保可以提交崩溃日志。 -protocol 定义了三个不同的回调,可以在应用中使用这些回调来通知发生 CrashesDelegate 情况:
在 SDK 发送崩溃日志之前,将调用以下回调
- (void)crashes:(MSACCrashes *)crashes willSendErrorReport:(MSACErrorReport *)errorReport {
// Your code, e.g. to present a custom UI.
}
func crashes(_ crashes: Crashes, willSend errorReport: ErrorReport) {
// Your code, e.g. to present a custom UI.
}
如果终结点出现网络问题或中断,并且重启应用,则进程重启后会再次 willSendErrorReport 触发。
SDK 成功发送故障日志后,将调用以下回调
- (void)crashes:(MSACCrashes *)crashes didSucceedSendingErrorReport:(MSACErrorReport *)errorReport {
// Your code, e.g. to hide the custom UI.
}
func crashes(_ crashes: Crashes, didSucceedSending errorReport: ErrorReport) {
// Your code goes here.
}
如果 SDK 无法发送崩溃日志,将调用以下回调
- (void)crashes:(MSACCrashes *)crashes didFailSendingErrorReport:(MSACErrorReport *)errorReport withError:(NSError *)error {
// Your code goes here.
}
func crashes(_ crashes: Crashes, didFailSending errorReport: ErrorReport, withError error: Error) {
// Your code goes here.
}
接收 didFailSendingErrorReport 表示发生不可恢复的错误,如 4xx 代码。 例如 ,401 表示 appSecret 错误。
如果是网络问题,则不触发此回调。 在这种情况下,SDK 会不断重试 (,并且还会在网络连接关闭时暂停重试) 。
向崩溃报告添加附件
可以将二进制和文本附件添加到崩溃报告。 SDK 会随故障一起发送它们,以便可以在门户App Center它们。 在从以前的应用程序启动发送存储的崩溃之前,将调用以下回调。 崩溃时不会调用它。 以下示例演示了如何将文本和图像附加到崩溃:
- (NSArray<MSACErrorAttachmentLog *> *)attachmentsWithCrashes:(MSACCrashes *)crashes
forErrorReport:(MSACErrorReport *)errorReport {
MSACErrorAttachmentLog *attachment1 = [MSACErrorAttachmentLog attachmentWithText:@"Hello world!" filename:@"hello.txt"];
MSACErrorAttachmentLog *attachment2 = [MSACErrorAttachmentLog attachmentWithBinary:[@"Fake image" dataUsingEncoding:NSUTF8StringEncoding] filename:@"fake_image.jpeg" contentType:@"image/jpeg"];
return @[ attachment1, attachment2 ];
}
func attachments(with crashes: Crashes, for errorReport: ErrorReport) -> [ErrorAttachmentLog]? {
let attachment1 = ErrorAttachmentLog.attachment(withText: "Hello world!", filename: "hello.txt")
let attachment2 = ErrorAttachmentLog.attachment(withBinary: "Fake image".data(using: String.Encoding.utf8), filename: nil, contentType: "image/jpeg")
return [attachment1!, attachment2!]
}
备注
大小限制当前为 7 MB。 尝试发送更大的附件将触发错误。
启用或禁用App Center崩溃
可以在运行时启用和App Center崩溃。 如果禁用它,SDK 将不会对应用执行任何崩溃报告。
[MSACCrashes setEnabled:NO];
Crashes.enabled = false
若要再次App Center崩溃,请使用同一 API,但作为 YES / true 参数传递。
[MSACCrashes setEnabled:YES];
Crashes.enabled = true
状态在应用程序启动时一直保留于设备的存储中。
备注
此方法只能在启动后 Crashes 使用。
检查App Center崩溃是否已启用
还可以检查是否App Center崩溃:
BOOL enabled = [MSACCrashes isEnabled];
var enabled = Crashes.enabled
备注
此方法只能在启动后 Crashes 使用,它始终在启动 false 之前返回。
禁用 Mach-o 异常处理
默认情况下,App Center 崩溃使用 Mach-o 异常处理程序通过 Mach-o 异常服务器捕获严重信号,如堆栈溢出。
disableMachExceptionHandler-方法提供禁止通过 mach-o 异常服务器捕获严重信号的选项。 如果要禁用 Mach-o 异常处理程序,则应在启动 SDK 之前 调用此方法。 典型的安装代码将如下所示:
[MSACCrashes disableMachExceptionHandler];
[MSACAppCenter start:@"{Your App Secret}" withServices:@[[MSACAnalytics class], [MSACCrashes class]]];
Crashes.disableMachExceptionHandler()
AppCenter.start(withAppSecret: "{Your App Secret}", services: [Analytics.self, Crashes.self])