App Center (iOS) 當機

重要

Visual Studio App Center 已排定於 2025 年 3 月 31 日淘汰。 雖然您可以繼續使用 Visual Studio App Center,直到完全淘汰為止,但有數個建議的替代方案可以考慮移轉至。

深入瞭解支持時程表和替代方案。

App Center 當機會在每次應用程式當機時自動產生當機記錄。 記錄會先寫入裝置的記憶體,當使用者再次啟動應用程式時,當機報告會傳送至 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 使用,它一律會傳回 NOfalse 啟動之前。

注意

在某些情況下,記憶體不足的裝置無法傳送事件。

應用程式在上一個工作階段中是否當機?

在啟動 SDK 之後,您可以隨時檢查應用程式是否在上一次啟動時損毀:

[MSACCrashes hasCrashedInLastSession];
Crashes.hasCrashedInLastSession

如果您想要在發生當機之後調整應用程式的行為或 UI,這會很有用。

注意

這個方法只能在啟動之後 MSACCrashes 使用,它一律會傳回 NOfalse 啟動之前。

上次當機的詳細數據

如果您的應用程式先前損毀,您可以取得最後一次當機的詳細數據。

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:如果您想要決定是否需要處理特定當機,請在採用 -protocol 的 類別CrashesDelegate中實作 -method。 例如,您可能想要忽略系統層級損毀,而且您不想傳送至 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 訊息。 如果您使用警示來進行此動作,如同我們在上述範例中所做的一樣,您會從 -callback 的實作 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,告知使用者您的應用程式正在提交當機報告,或者,如果您的app在啟動後快速當機,您想要調整應用程式的行為,以確保可以提交當機記錄。 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])