Иногда 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
.....

person Breezeight    schedule 03.10.2012    source источник
comment
Вы уверены, что это не из-за утечки памяти? У меня аналогичная проблема, но я уже определил причину. IOS 6 MKMapView занимает в 10 раз больше памяти, чем предыдущий. Мое приложение предназначено для отображения материалов на картах, и его размер увеличился с 30 МБ до 280 МБ. Я пытаюсь решить эту проблему, но пока понятия не имею.   -  person Trein    schedule 05.10.2012
comment
Привет @trein, исключением является SIGSEGV, насколько я понимаю, это должно быть вызвано плохим доступом к памяти.   -  person Breezeight    schedule 16.10.2012


Ответы (4)


У нас была аналогичная проблема, когда пользователь использовал наше приложение в фоновом режиме, когда мы открывали окно, которое включает в себя подвид карты. Сбой, похоже, произошел из-за того, что карта использовала вызов openGL, пока мы находились в фоновом режиме. Нам пришлось заключить создание подвида карты в проверку, как показано ниже:

UIApplicationState appState = [[UIApplication sharedApplication] applicationState];
    if( (appState != UIApplicationStateBackground) && (appState != UIApplicationStateInactive))
    {
        // Do map subview initialization...
    }
    else
    {
        self.attemptedToLoadMap = YES;
    }

Мы сэкономили на bool, чтобы, если приложение вернется на передний план, мы сможем добавить подпредставление для отображения.

Вы должны делать это каждый раз, когда манипулируете картой таким образом, чтобы вызвать операцию повторного рисования (например, добавление аннотации).

person stuckj    schedule 25.10.2012
comment
Привет, @stuckj, это исправляет ваш сбой? - person Breezeight; 30.10.2012
comment
Приложение было одобрено на выходных. И да, похоже, он обратился к нему. Больше не вижу отчетов об этом в отчетах о сбоях. - person stuckj; 06.11.2012
comment
Любые идеи о том, почему вам также нужно проверять UIApplicationStateInactive? Я имею в виду, что пользовательский интерфейс приложения все еще виден, просто он не самый передний. Я добавил проверку только для UIApplicationStateBackground и все еще получаю отчеты о сбоях для этого. - person samvermette; 06.02.2013
comment
Вы переходите в неактивное состояние перед переходом в фоновый режим. К тому времени, когда ваше состояние станет UIApplicationStateBackground, вы уже находитесь в фоновом режиме, поэтому вы уже рискуете, что операция пользовательского интерфейса карты убьет вещи до того, как эта проверка будет выполнена. Проверка на неактивность также закрывает это окно больше. Вероятно, все еще ВОЗМОЖНО получить сбой даже при этой проверке, но это должно закрыть окно гораздо больше. - person stuckj; 06.02.2013
comment
Хм. Наш вид карты создается с помощью NIB. Почему у меня закрадывается подозрение, что это уже не лучшая идея. : -o - person Joe D'Andrea; 19.02.2013
comment
На самом деле, если я могу спросить, я время от времени добавляю / удаляю аннотации, но к этому моменту карта уже создана (конечно, отсюда и перерисовка). Означает ли это, что я оставлю NIB в покое и просто буду проверять реальность при работе с аннотациями? (Хотя в моем случае сбой происходит после вызова initWithCoder:, возможно, его сложнее решить.) - person Joe D'Andrea; 19.02.2013
comment
Если вы получаете аналогичную трассировку стека (заканчивающуюся на gpus_ReturnNotPermittedKillClient) от initWithCoder, то это звучит так, как будто ваш NIB с картой инициализируется в фоновом режиме (или, по крайней мере, запускается рядом, когда вы работаете в фоновом режиме). Я не знаю, что использование NIB конкретно вызовет проблему, но это дает вам меньше контроля над тем, когда он инициализируется, поэтому вы можете захотеть переключиться на программную инициализацию. Мы сделали это в синглтоне (также устраняет некоторые ужасные утечки памяти, которые есть на картах iOS ...). - person stuckj; 20.02.2013
comment
Спасибо, stuckj - оценил. Действительно, я получаю ту же самую трассировку стека. Наш вид карты является частью вида, отображаемого в контроллере навигации, который сам находится в контроллере панели вкладок. Таким образом, есть лишние инициализации NIB. Я переместил представление карты из NIB, чтобы посмотреть, помогает ли это ... но теперь вам интересно узнать об этом синглтоне. Хм! - person Joe D'Andrea; 20.02.2013
comment
Идея синглтона, которую мы действительно использовали, чтобы обойти проблему с памятью (не уверен, исправлена ​​ли она в 6.1 ... еще не проверена). Мы наблюдали утечку огромного количества памяти каждый раз, когда исчезал вид карты. Вероятно, кеш, но на самом деле это была утечка, так как это привело бы к увеличению нагрузки на память, что привело бы к сбоям. Особенно, если люди использовали камеру в приложении после того, как карта исчезла. - person stuckj; 21.02.2013

http://developer.apple.com/library/ios/#qa/qa1766/_index.html

Этот технический QA решает эту проблему

person futbolpal    schedule 04.01.2013
comment
Я не использую OpenGL, но Apple использует для карт iOS 6. Может быть, в этом случае им стоит следить за собственными техническими вопросами и ответами? Eek. - person Joe D'Andrea; 19.02.2013
comment
Плохой выбор слов. В нем немного объясняется, что происходит, но в случае, когда за это отвечает фреймворк, предоставленный Apple (MapKit), он не объясняет, как решить проблему. - person software evolved; 28.05.2015

Мы нашли причину этого в нашем приложении, поэтому я хотел опубликовать решение на случай, если оно поможет кому-то еще. Наш основной контроллер представления отслеживает значительные изменения местоположения, когда он отображается, и прекращает мониторинг, когда он скрыт. Некоторое количество наших пользователей столкнулись с несвязанным сбоем на этом экране, из-за которого приложение не отслеживало. Когда приложение зарегистрировано для значительных обновлений изменения местоположения, 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 запустит приложение в фоновом режиме, и вы получите сбой. Мы смогли достать один из телефонов наших пользователей и изучить журналы сбоев. Все аварии произошли во время ее поездки на работу и с работы.

person Matthew Daugherty    schedule 16.12.2014

Я сталкиваюсь с аналогичной трассировкой стека. Я заметил, что в консоли более подробно описывается реальная проблема: вы не можете использовать графический процессор в фоновом режиме. Карты с iOS 5 были основаны на плитках, поэтому я предполагаю, что не использовал графический процессор, но новые карты в iOS 6 используют векторную графику и, следовательно, графический процессор. В результате любая работа с картой, которая раньше была в фоновом режиме, больше не может быть.

person hunterhacker    schedule 08.10.2012
comment
Привет, @hunterhacker, я получаю трассировку стека от пользователей. Я не могу воспроизвести сбой на своем устройстве. Не могли бы вы помочь мне воспроизвести ошибку? - person Breezeight; 16.10.2012
comment
Я не мог воссоздать его в симуляторе, вероятно, потому, что симулятор не использует графический процессор для генерации карты. Трассировка надежно выполнялась всякий раз, когда я пытался создать новый вид карты во время работы в фоновом режиме, получая обратный вызов о новом местоположении пользователя. Извините за задержку с ответом, не знаю, как я должен быть уведомлен о комментариях к ответам, но я не получил его. - person hunterhacker; 15.11.2012