Иногда iOS 6 MKMapView падает в initWithFrame
У меня есть приложение в магазине Apple, и после обновления iOS6 у меня есть сто отчетов о сбоях в MKMapView
. Я не могу воспроизвести крах на своих устройствах. Это выглядит как проблема с EAGLContext
. Мы не используем OpenGL в нашем приложении, но у нас есть несколько экземпляров MKMapView
в разных контроллерах.
Я нашел аналогичную проблему здесь iOS 6 сбой приложений в EAGLContext при отображении карт, но они используют OpenGL.
Здесь есть обратная трассировка:
Exception Type: SIGSEGV
Exception Codes: SEGV_ACCERR at 0x1
Crashed Thread: 0
Thread 0 Crashed:
0 libGPUSupportMercury.dylib 0x00000e22 gpus_ReturnNotPermittedKillClient + 10
1 libGPUSupportMercury.dylib 0x3bccc5fb gldCreateContext + 190
2 GLEngine 0x344c2b15 gliCreateContextWithShared + 676
3 OpenGLES 0x0000491d -[EAGLContext initWithAPI:properties:] + 1433
4 OpenGLES 0x000042d7 -[EAGLContext initWithAPI:sharedWithCompute:] + 143
5 VectorKit 0x00011c81 -[VGLGPU init] + 105
6 VectorKit 0x000d4659 __24+[VGLGPU sharedInstance]_block_invoke_0 + 49
7 libdispatch.dylib 0x000014b7 _dispatch_client_callout + 23
8 libdispatch.dylib 0x000073f7 dispatch_once_f$VARIANT$mp + 43
9 VectorKit 0x00011c13 +[VGLGPU sharedInstance] + 39
10 VectorKit 0x00001db1 -[VKMainLoop updateLinkState] + 485
11 VectorKit 0x00001955 -[VKScreenCanvas _updateDisplayStatus:] + 109
12 UIKit 0x0001c371 -[UIView initWithFrame:] + 129
13 VectorKit 0x00010ca5 -[VGLScreenCanvas initWithFrame:context:] + 53
14 VectorKit 0x00010a7d -[VKScreenCanvas initWithFrame:context:] + 57
15 VectorKit 0x00010a3f -[VKScreenCanvas initWithFrame:] + 39
16 VectorKit 0x000106bd -[VKMapCanvas initWithFrame:shouldRasterize:] + 65
17 VectorKit 0x000104bb -[VKMapView initWithFrame:andGlobe:shouldRasterize:] + 647
18 MapKit 0x0000dc95 -[MKMapView _commonInitAndEnableLoading:fromIB:] + 725
19 MapKit 0x0000d811 -[MKMapView initWithFrame:] + 257
.....
Ответы
Ответ 1
У нас возникла аналогичная проблема, когда пользователь заглядывал в наше приложение так же, как мы выворачиваем окно, которое включает в себя подкласс отображения. Похоже, что авария произошла из-за карты, используя вызов openGL, когда мы находимся в фокусе. Нам пришлось обернуть создание подзаголовка карты в чеке, как показано ниже:
UIApplicationState appState = [[UIApplication sharedApplication] applicationState];
if( (appState != UIApplicationStateBackground) && (appState != UIApplicationStateInactive))
{
// Do map subview initialization...
}
else
{
self.attemptedToLoadMap = YES;
}
Мы сэкономили bool, так что, если приложение вернется на передний план, мы можем добавить subview для отображения.
Вы должны делать это в любое время, когда вы манипулируете картой таким образом, который вызывает операцию повторного рисования (например, добавление аннотации).
Ответ 2
http://developer.apple.com/library/ios/#qa/qa1766/_index.html
Этот технический QA адрес этой проблемы
Ответ 3
Мы нашли причину этого в нашем приложении, поэтому я захотел опубликовать решение, если оно поможет кому-то еще. Наш основной контроллер просмотра контролирует значительные изменения местоположения при его отображении и прекращает мониторинг, когда он скрыт. Некоторое количество наших пользователей столкнулось с несвязанным сбоем на этом экране, что оставило мониторинг приложений. Когда приложение зарегистрировалось для значительных обновлений изменения местоположения, iOS фактически запустит приложение в фоновом режиме, если оно не будет запущено, чтобы рассказать об этом новом местоположении. Поскольку наше приложение отображает карту, когда она впервые появляется, это вызвало сбой. Поддержка Apple подтвердила, что на 32-разрядных устройствах под управлением iOS 8.x есть ошибка, которая может привести к сбою, если MapView (или другой контекст OpenGL) обновляется, когда приложение находится в фоновом режиме.
Мы изменили наш код, чтобы, если приложение запускается из-за значительного изменения местоположения, мы немедленно прекращаем мониторинг и генерируем исключение, чтобы свернуть приложение. Это полностью невидимо для пользователя, поэтому они не замечают краха, и это предотвращает дальнейшие сбои.
- (void)validateLaunchWithOptions:(NSDictionary *)launchOptions
{
if (launchOptions[@"UIApplicationLaunchOptionsLocationKey"]) {
// the app was launched due to a significant location change, which is not valid and causes crashes
// prevent this from happening again by disabling significant location monitoring
CLLocationManager *locationManager = [[CLLocationManager alloc] init];
[locationManager stopMonitoringSignificantLocationChanges];
// intentionally crashing the app here; it is not in a good state and it needs to be prevented from
// getting to any code that would re-enable significant location monitoring
@throw [NSException exceptionWithName:@"com.redacted.significantLocationLaunch"
reason:@"app may not be launched due to significant location changes"
userInfo:@{}];
}
}
Мы видели тысячи этой аварии, но не смогли ее дублировать на наших тестовых устройствах, пока не выяснили причину. Если вы хотите его дублировать (а также подтвердить исправление), @throw исключение сразу же после того, как ваше приложение начнет отслеживать значительные изменения местоположения. После сбоя приложения перейдите на диск. Как только ваш телефон переключит сотовые башни, iOS запустит приложение в фоновом режиме, и вы получите крах. Мы смогли получить доступ к одному из наших телефонов пользователей и проверить журналы сбоев. Все аварии произошли во время ее поездок на работу и с работы.
Ответ 4
Я столкнулся с аналогичной трассировкой стека. Я заметил, что в консоли он дает больше информации о реальной проблеме: вы не можете использовать GPU в фоновом режиме. Карты с iOS 5 были основаны на плитке, поэтому я предполагаю, что не использовал GPU, но новые карты в iOS 6 используют векторную графику и, следовательно, графический процессор. В результате любая работа с картами, которая раньше была в фоновом режиме, больше не может быть.