重要
Visual Studio App Center 于 2025 年 3 月 31 日停用,但分析和诊断功能除外,这些功能将继续受支持,直到 2026 年 6 月 30 日。 了解详细信息。
每次应用发生崩溃时,App Center Crashes 功能都会自动生成一份崩溃日志。 日志首先写入设备的存储,当用户再次启动应用时,崩溃报告将发送到 App Center。 收集崩溃功能适用于 beta 应用和上线应用,即提交到 App Store 的应用。 故障日志包含有助于修复崩溃的重要信息。
如果尚未在应用程序中设置 SDK,请按照 “入门 ”部分进行作。
此外,iOS 上的崩溃日志需要符号化,请查看 App Center 诊断文档 ,其中介绍了如何为应用提供符号。
注释
如果附加到调试器,SDK 不会转发任何故障日志。 请确保在应用崩溃时没有附加调试器。
注释
若要接收正确符号化的堆栈跟踪,请确保禁用 bitcode。 可以在 App Center 的 iOS 符号化文档中了解有关 bitcode 的详细信息。
注释
在 4.0.0
版本中引入了 App Center 的重大变更。 请按照“迁移到 App Center SDK 4.0.0 及更高”部分的指引,将 App Center 从之前的版本迁移。
扩展中的崩溃报告
App Center 支持 iOS 扩展中的崩溃报告。 用法与容器应用程序中的用法相同。
触发测试崩溃
App Center 的崩溃模块提供了一个 API,用于生成测试崩溃,以方便测试 SDK。 此 API 只能在测试/beta 应用中使用,并且不会在生产应用中执行任何作。
[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
-protocol,其所有方法都是可选的。
注册为委托
[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
;Crashes 模块会自动为您处理日志发送。
以下方法演示如何设置用户确认处理程序:
[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,告知用户你的应用正在提交崩溃报告,或者,如果应用在启动后快速崩溃,你想要调整应用的行为,以确保可以提交崩溃日志。
CrashesDelegate
-protocol 定义了三个不同的回调,你可以在应用中使用它来通知发生的情况:
在 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 异常处理
默认情况下,App Center 崩溃使用 Mach 异常处理程序通过 Mach 异常服务器捕获致命信号,例如堆栈溢出。
disableMachExceptionHandler
-method 提供了一个选项,用于通过 Mach 异常服务器禁用捕获致命信号。 如果要禁用 Mach 异常处理程序,应在启动 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])