Отладочный сбой в CoreGraphics / MapKit - PullRequest
10 голосов
/ 25 ноября 2011

У меня периодически возникает сбой при запуске приложения на iPhone.Все сбои идентичны и в некоторой степени связаны с наложениями MKMapView (MKCircleViews).

Из типичного отчета о сбое iPhone 4s:

Заголовок отчета:

Hardware Model:      iPhone4,1
Process:         EL-GPS-01 [1021]
Path: /var/mobile/Applications/61288E15-74B5-45B9-99A9-E0B58C767816/EL-GPS-01.app/EL-GPS-01
Identifier:      EL-GPS-01
Version:         ??? (???)
Code Type:       ARM (Native)
Parent Process:  launchd [1]

Date/Time:       2011-11-22 15:59:41.065 +0000
OS Version:      iPhone OS 5.0.1 (9A405)
Report Version:  104

Exception Type:  EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x00000000
Crashed Thread:  6

Исбой потока:

Thread 6 name: Dispatch queue: com.apple.root.default-priority
Thread 6 Crashed:
0 ??? 0000000000 0 + 0
1 CoreGraphics 0x319a87c2 0x31967000 + 268226
2 CoreGraphics 0x3199a9e6 0x31967000 + 211430
3 MapKit 0x37ec3564 0x37e6f000 + 345444
4 MapKit 0x37ec3652 0x37e6f000 + 345682
5 MapKit 0x37ecc0a4 0x37e6f000 + 381092
6 QuartzCore 0x3341be18 0x33410000 + 48664
7 QuartzCore 0x334d77e0 0x33410000 + 817120
8 QuartzCore 0x3346af24 0x33410000 + 372516
9 libdispatch.dylib 0x3797e892 0x3797b000 + 14482
10 libsystem_c.dylib 0x360e31ca 0x360d9000 + 41418
11 libsystem_c.dylib 0x360e30a0 0x360d9000 + 41120

Когда происходит сбой приложения, когда мой iPhone подключен к моему ноутбуку, я получаю следующее на панели вывода:

warning: check_safe_call: could not restore current frame
warning: Unable to restore previously selected frame.

Отладчик вообще ничего не дает мне,и навигатор проблем показывает сбойный поток без стека.

Существует очень простой проект, освещающий проблему здесь:

https://github.com/1ndivisible/MKOverlayBug

git@ github.com: 1ndivisible / MKOverlayBug.git

Я не уверен, как подойти к этому.Есть ли здесь какая-либо информация, которую я могу использовать?Похоже, сбой происходит глубоко в рамках.

Ответы [ 4 ]

3 голосов
/ 09 февраля 2012

Я думаю, что у вас недостаточно памяти или вы столкнулись с ошибкой в ​​MapKit.Но в его защиту не похоже, что вы используете наложения и представления MK правильно и перегружаете MKMapView, отслеживая так много потенциальных наложений.Дело в точке.При следующем методе вы добавляете 50 оверлеев к текущему местоположению:

-(void)addOverlays
{
    CLLocation *currentLocation = self.mapView.userLocation.location;

    for(int i = 0; i < 50; i++)
    {
       MKCircle *circle = [MKCircle circleWithCenterCoordinate:currentLocation.coordinate radius:50];
       [self.mapView addOverlay:circle];
    }
}

со временем это может добавить к большому количеству оверлеев, которые MKMapView должен отслеживать, и MKView, которые он потенциально долженпоказывать сразу.С вашим примером кода и симулятором местоположения симулятора iPhone простой маршрут езды на велосипеде собрал более 1800 MKCircle и MKCircleViews в MKMapView.

Вот пара моментов, о которых следует помнить:

  1. Не добавляйте столько оверлеев в каждой локации.1 достаточно.50 - это излишество.
  2. Для каждого местоположения должно быть достаточно одного MKCircle.Не уверен, почему вы решили отслеживать и рисовать так много кругов в каждом месте.
  3. Постарайтесь более эффективно передавать наложения в MapView.Дайте ему только те наложения, которые необходимы для той части карты, которую он показывает.Посмотрите видео WWDC2011 «Сессия 111 - Географическая визуализация информации с помощью MapKit», в котором показано, как оптимизировать этот код или пример кода HazardMap.

Вы можете сделать что-то вроде этого:

-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
  {
    // Add it to an NSArray that you use to keep track of ALL the overlays
    [self.allOverlays addObject: MKCircle *circle = [MKCircle circleWithCenterCoordinate:currentLocation.coordinate radius:50]];

     // Now add it to the mapView if it is in the current region

     // code to check to see if currentLocation is within the current map region

     if (overlayIsInMapRegion){
         [mapView addOverlay: circle];
     } 
}

Затем, когда регион изменяется, вычислите наложения, которые необходимы, когда MapView вызывает метод делегата:

- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated

получите регион из mapView и создайте массив наложений, которые расположены в этом регионе.,Что-то вроде:

- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated{
    // Create a method that takes the region and calculates which overlays it contains
    NSArray *newOverlays=[self overlaysForRegion: mapView.region fromAllOverlays: self.allOverlays];
    if ([newOverlays count]>0){
         [mapView removeOverlays];
         [mapView addOverlays: newOverlays];
    }

}

Надеюсь, это поможет.Удачи!

Тим

3 голосов
/ 09 февраля 2012

Это известная ошибка. Apple признала это. Там в настоящее время нет исправления. Все, что вы можете сделать, это объединить вашу графику в меньшее количество аннотаций. Я обнаружил, что <= 3 аннотации безопасны. </p>

1 голос
/ 25 ноября 2011

KERN_INVALID_ADDRESS в 0x00000000 Сбой потока: 6

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

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

0 голосов
/ 15 февраля 2012

В этом случае он может пытаться выполнить код по адресу 0 (а не получить доступ к данным оттуда). Если вы снова столкнетесь с этим в отладчике, проверьте значение в реестре ПК. Если значение равно нулю, то вы выполняете с нуля, а не извлекаете данные.

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

...