Сбои Центра приложений (iOS)

Важно!

Прекращение поддержки Центра приложений Visual Studio запланировано на 31 марта 2025 г. Хотя вы можете продолжать использовать Центр приложений Visual Studio, пока он не будет полностью выведен из эксплуатации, существует несколько рекомендуемых вариантов, на которые вы можете рассмотреть возможность миграции.

Узнайте больше о сроках поддержки и альтернативных вариантах.

Сбои Центра приложений автоматически создают журнал сбоев при каждом сбое приложения. Журнал сначала записывается в хранилище устройства, и когда пользователь снова запустит приложение, отчет о сбоях будет отправлен в Центр приложений. Сбор сбоев работает как для бета-, так и для динамических приложений, т. е. для приложений, отправленных в App Store. Журналы сбоев содержат ценные сведения, которые помогут устранить сбои.

Если вы еще не настроили пакет SDK в приложении, следуйте инструкциям в разделе начало работы.

Кроме того, журналы сбоев в iOS требуют символики, проверка из документации по диагностике Центра приложений, в которых объясняется, как предоставить символы для приложения.

Примечание

Пакет SDK не будет пересылать журнал сбоев, если вы подключены к отладчику. Убедитесь, что отладчик не подключен при сбое приложения.

Примечание

Чтобы получить правильно символические трассировки стека, убедитесь, что бит-код отключен. Дополнительные сведения о бит-коде см. в документации по символике iOS в Центре приложений.

Примечание

4.0.0 В версии Центра приложений были введены критические изменения. Чтобы перенести Центр приложений с предыдущих версий, следуйте инструкциям в разделе Миграция в пакет SDK для Центра приложений 4.0.0 и более поздних версий.

Отчеты о сбоях в расширениях

Центр приложений поддерживает отчеты о сбоях в расширениях iOS. Использование такое же, как и в контейнерном приложении.

Создание тестового сбоя

Сбои Центра приложений предоставляют API для создания тестового сбоя для простого тестирования пакета SDK. Этот API можно использовать только в тестовых или бета-версиях приложений и не будет выполнять никаких действий в рабочих приложениях.

[MSACCrashes generateTestCrash];
Crashes.generateTestCrash()

Дополнительные сведения о предыдущем сбое

При сбоях центра приложений есть два API, которые предоставляют дополнительные сведения на случай сбоя приложения.

Приложение получило предупреждение о нехватке памяти в предыдущем сеансе?

В любой момент после запуска пакета SDK можно проверка, если приложение получило предупреждение о памяти в предыдущем сеансе:

[MSACCrashes hasReceivedMemoryWarningInLastSession];
Crashes.hasReceivedMemoryWarningInLastSession

Примечание

Этот метод следует использовать только после Crashes запуска, он всегда будет возвращать NO или false до запуска.

Примечание

В некоторых случаях устройство с низким объемом памяти не может отправлять события.

Произошел сбой приложения в предыдущем сеансе?

В любой момент после запуска пакета SDK можно проверка, если приложение не произошло при предыдущем запуске:

[MSACCrashes hasCrashedInLastSession];
Crashes.hasCrashedInLastSession

Это удобно, если вы хотите настроить поведение или пользовательский интерфейс приложения после сбоя.

Примечание

Этот метод следует использовать только после MSACCrashes запуска, он всегда будет возвращать NO или false до запуска.

Сведения о последнем сбое

Если приложение ранее завершалось сбоем, вы можете получить сведения о последнем сбое.

MSACErrorReport *crashReport = [MSACCrashes lastSessionCrashReport];
var crashReport = Crashes.lastSessionCrashReport

Примечание

Этот метод следует использовать только после Crashes запуска. Он всегда возвращается nil перед запуском.

Существует множество вариантов использования этого API. Наиболее распространенными являются люди, которые вызывают этот API и реализуют свои пользовательские CrashesDelegate.

Настройка использования сбоев Центра приложений

Сбои Центра приложений предоставляют разработчикам обратные вызовы для выполнения дополнительных действий до и при отправке журналов сбоев в Центр приложений.

Чтобы добавить пользовательское поведение, необходимо внедрить CrashesDelegateпротокол -protocol, все его методы являются необязательными.

Регистрация в качестве делегата

[MSACCrashes setDelegate:self];
Crashes.delegate = self

Примечание

Необходимо задать делегат перед вызовом AppCenter.start, так как центр приложений запускает обработку сразу после запуска.

Следует ли обрабатывать сбой?

crashes:shouldProcessErrorReport:Реализуйте -method в классе , который принимает CrashesDelegateпротокол ,если вы хотите решить, нужно ли обрабатывать конкретный сбой. Например, может произойти сбой на уровне системы, который вы хотите игнорировать и не хотите отправлять в Центр приложений.

- (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.
}

Обработано ошибок

Центр приложений также позволяет отслеживать ошибки с помощью обрабатываемых исключений с помощью 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)
}

Если конфиденциальность пользователей важна для вас, вы можете получить подтверждение пользователя перед отправкой отчета о сбое в Центр приложений. Пакет SDK предоставляет обратный вызов, который сообщает о сбоях Центра приложений о том, что ожидает подтверждения пользователя перед отправкой отчетов о сбоях.

Если вы решили сделать это, вы несете ответственность за получение подтверждения пользователя, например с помощью диалогового запроса с одним из следующих вариантов: Всегда отправлять, Отправлять и Не отправлять. В зависимости от входных данных вы сообщите Центру приложений, что делать, а затем будет обработано соответствующим образом.

Примечание

Пакет SDK не отображает диалоговое окно для этого, приложение должно предоставить собственный пользовательский интерфейс, чтобы запросить согласие пользователя.

Примечание

Приложение не должно вызывать 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 в блок обработчика выше, приложение должно получить разрешение пользователя и предоставить пакету SDK с результатом с помощью следующего API. Если вы используете для этого оповещение, как в приведенном выше примере, вы будете вызывать его из реализации обратного 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)

Получение сведений о состоянии отправки для журнала сбоев

Иногда требуется узнать состояние сбоя приложения. Распространенный вариант использования заключается в том, что может потребоваться показать пользовательский интерфейс, который сообщает пользователям, что приложение отправляет отчет о сбое, или, если приложение быстро завершается сбоем после запуска, необходимо настроить поведение приложения, чтобы убедиться, что журналы сбоев можно отправить. Протокол 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 отправит их вместе с аварийным завершением, чтобы их можно было увидеть на портале Центра приложений. Следующий обратный вызов будет вызываться непосредственно перед отправкой сохраненного сбоя из предыдущих запусков приложений. Он не будет вызываться при сбое. Ниже приведен пример вложения текста и изображения в сбой:

- (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 МБ. Попытка отправить вложение большего размера вызовет ошибку.

Включение или отключение сбоев Центра приложений во время выполнения

Вы можете включить и отключить сбои Центра приложений во время выполнения. Если вы отключите его, пакет SDK не будет сообщать о сбоях для приложения.

[MSACCrashes setEnabled:NO];
Crashes.enabled = false

Чтобы снова включить сбои Центра приложений, используйте тот же API, но передайте YES/true в качестве параметра.

[MSACCrashes setEnabled:YES];
Crashes.enabled = true

Состояние сохраняется в хранилище устройства при запусках приложений.

Примечание

Этот метод следует использовать только после Crashes запуска.

Проверьте, включены ли сбои Центра приложений

Вы также можете проверка, включены ли сбои Центра приложений:

BOOL enabled = [MSACCrashes isEnabled];
var enabled = Crashes.enabled

Примечание

Этот метод следует использовать только после Crashes запуска. Он всегда возвращается false перед запуском.

Отключение обработки исключений Mach

По умолчанию сбои Центра приложений используют обработчик исключений Mach для перехвата неустранимых сигналов, например переполнения стека, через сервер исключений Mach.

Метод disableMachExceptionHandler-предоставляет возможность отключить перехват неустранимых сигналов через сервер исключений 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])