Ocasionalmente iOS 6 MKMapView falla en initWithFrame

Tengo una aplicación en la tienda de Apple y, después de la actualización de iOS6, tengo cientos de informes de MKMapView dentro de MKMapView . No puedo gestionar reproducir el locking en mis dispositivos. Parece un problema con EAGLContext . No utilizamos OpenGL en nuestra aplicación, pero tenemos más de una instancia de MKMapView en un controller diferente. Encontré un problema similar aquí, la aplicación iOS 6 se bloquea en EAGLContext cuando se muestran maps, pero usan OpenGL.

Aquí está el backtrace:

 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 gliCreateContextWithShanetworking + 676 3 OpenGLES 0x0000491d -[EAGLContext initWithAPI:properties:] + 1433 4 OpenGLES 0x000042d7 -[EAGLContext initWithAPI:shanetworkingWithCompute:] + 143 5 VectorKit 0x00011c81 -[VGLGPU init] + 105 6 VectorKit 0x000d4659 __24+[VGLGPU shanetworkingInstance]_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 shanetworkingInstance] + 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 ..... 

Estábamos teniendo un problema similar cuando la experiencia del usuario nuestra aplicación, justo cuando estamos apareciendo una window que incluye una subvista de map. El crash parecía estar sucediendo debido al map con una llamada openGL mientras estamos en segundo plano. Tuvimos que envolver la creación de la subvista del map en un cheque como el siguiente:

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

Hemos guardado el bool de modo que si la aplicación vuelve al primer plano, podemos agregar la subvista para su visualización.

Tiene que hacer esto en cualquier momento que esté manipulando el map de una manera que provoque una operación de re-draw (por ejemplo, agregar una anotación).

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

Este control de calidad técnico aborda este problema.

Encontramos la causa de esto en nuestra aplicación, así que quería publicar la solución en caso de que ayudara a alguien más. Nuestro controller de vista primaria supervisa los cambios de location significativos cuando se muestra y detiene la supervisión cuando está oculto. Algunos de nuestros usuarios experimentaron una falla no relacionada en esta pantalla, que dejó la monitorización de la aplicación. Cuando una aplicación se ha registrado para actualizaciones importantes de cambio de location, iOS realmente ejecutará la aplicación en segundo plano si no se está ejecutando para informarle sobre la nueva location. Como nuestra aplicación muestra un map cuando aparece por primera vez, esto provocó un locking. El soporte de Apple confirmó con nosotros que hay un error en dispositivos de 32 bits que ejecutan iOS 8.x que pueden causar un locking si MapView (u otro context de OpenGL) se actualiza mientras la aplicación está en segundo plano.

Cambiamos nuestro código para que, si la aplicación se inicia debido a un cambio significativo en la location, dejamos de monitorear inmediatamente y hacemos una exception para bloquear la aplicación. Esto es completamente invisible para el usuario, por lo que no se da count del locking y evita que se produzcan más lockings.

 - (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.networkingacted.significantLocationLaunch" reason:@"app may not be launched due to significant location changes" userInfo:@{}]; } } 

Vimos miles de este locking, pero no pudimos duplicarlo en nuestros dispositivos de testing hasta que descubrimos la causa. Si desea duplicarlo (y también confirmar la corrección), obtenga una exception inmediatamente después de que su aplicación comience a monitorear cambios importantes en la location. Después de que la aplicación se bloquee, ve a tomar una unidad. Tan pronto como su teléfono cambie las torres de celulares, iOS iniciará la aplicación en segundo plano y obtendrá el locking. Pudimos tener en nuestras manos uno de nuestros teléfonos de usuarios e inspeccionar los loggings de fallas. Todos los crashs ocurrieron durante su viaje de ida y vuelta al trabajo.

Estoy frente a una huella de stack similar. Noté que en la console está dando más detalles sobre el problema real: no puedes usar la GPU mientras estás en segundo plano. Los maps con iOS 5 estaban basados ​​en mosaicos, así que supongo que no usé la GPU, pero los nuevos maps en iOS 6 usan charts vectoriales y, por lo tanto, la GPU. Como resultado, cualquier trabajo de map que solía estar en segundo plano ya no puede ser.