2013-05-22 2 views
1

Я пытаюсь узнать, как сбросить контакты на карте в iOS 6. У меня есть код, который компилируется и запускается, но который явно пропускает память - но когда я отпускаю (или autoRelease) объект mapData, с которым связано мое приложение. ОшибкаСбой после сброса контактов на карте в iOS6

Экземпляр 0x1b7ac0 класса AddressAnnotation был освобожден, а наблюдатели с ключевыми значениями все еще были зарегистрированы с ним. Наблюдательная информация просочилась и может даже ошибочно привязана к другому объекту. Установите точку останова на NSKVODeallocateBreak, чтобы остановиться здесь, в отладчике.

Существует более ранний пост только на этой ошибки, а также по отношению к MapKit:
Setting breakpoint at NSKVODeallocateBreak

Но это не помогает мне:
Во-первых, я не очень понимаю, ответ, но и его кажется, ответ не имеет отношения к моей проблеме, потому что я не имею не устанавливать наблюдателя каким-либо образом (что я знаю, что это!) Например, нигде в моем коде у меня есть строки

[addressAnnotation addObserver:self forKeyPath:kSelectedAnnotationObserverKeyPath options:NSKeyValueObservingOptionNew context:@"selectedOrDeselected"]; 

или что-нибудь иначе отдаленно похожие, которые были предложены b e проблема.

Сказав это, я также должен сказать, что я действительно не понимаю концепцию наблюдателя - я, конечно, создал пользовательский класс MapData, который является NSObject <MKAnnotation>, и я полагаю, что это также может быть источником проблема. Но я в основном ошеломлен.

Я попытался установить предложенную символическую точку останова, но мне это не полезно: я вижу, что у меня есть условие BAD ACCESS, но это все, что я действительно понимаю!

Код я написал это:

- (void) showRecordsOnMap 
{ 
    NSMutableArray *projectMapAnnotationsArray; 
    projectMapAnnotationsArray = [[NSMutableArray alloc] init]; 

    int i = 0; 
    for (i = 0; i < [currentProject.recordArray count]; i++) 
    { 
     Record *record = [[[Record alloc] init]autorelease]; 
     record = [currentProject.recordArray objectAtIndex:i]; 

     CLLocationCoordinate2D newCoordinate; 
     newCoordinate.latitude = record.latitude; 
     newCoordinate.longitude = record.longitude; 
     int tag = 0; 
     NSString *title; 
     title = [[[NSString alloc] init] autorelease]; 
     title = [NSString stringWithFormat:@"Record %d",record.record_ID]; 
     NSString *subtitle; 
     subtitle = [[[NSString alloc] init] autorelease]; 
     subtitle = [NSString stringWithFormat:@"Record %d",record.record_ID]; 

     MapData *mapData =[[MapData alloc] initWithCoordinate:newCoordinate withTag:tag withTitle:title withSubtitle:title]; 

     [projectMapAnnotationsArray addObject:mapData]; 

     //[mapData release]; 

    } 

    [projectMap addAnnotations:projectMapAnnotationsArray]; 
    [projectMapAnnotationsArray release]; 

} 

, а затем следующий Нужный бит

- (MKAnnotationView *) mapView:(MKMapView *)mapView 
      viewForAnnotation:(MapData *)annotation 
{  
    static NSString *record = @"record"; 

    //the result of the call is being cast (MKPinAnnotationView *) to the correct 
    //view class or else the compiler complains 
    MKPinAnnotationView *annotationView = (MKPinAnnotationView *)[projectMap 
                    dequeueReusableAnnotationViewWithIdentifier:record]; 
    if(annotationView == nil) 
    { 
     annotationView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:record] autorelease]; 
    } 

    //if((annotation).tag == 2) annotationView.pinColor = MKPinAnnotationColorRed; 
    //else annotationView.pinColor = MKPinAnnotationColorGreen; 

    annotationView.pinColor = MKPinAnnotationColorGreen; 
    //pin drops when it first appears 
    annotationView.animatesDrop=TRUE; 

    //tapping the pin produces a gray box which shows title and subtitle 
    annotationView.canShowCallout = YES; 

    return annotationView; 
} 

Этот код работает, до тех пор, пока объект MapData не освобождается. Но ясно, что мне нужно его освободить. Как еще один ключ, если я раскомментировать

// if((annotation).tag == 2) annotationView.pinColor = MKPinAnnotationColorRed; 
// else annotationView.pinColor = MKPinAnnotationColorGreen; 

я получаю другую ошибку:

[MKUserLocation tag]: unrecognized selector sent to instance 0x9fcb010 2013-05-22 23:05:13.726 Geo360[1175:c07] *** Terminating app due to uncaught exception 'NSInvalidArgumentException' , reason: ' -[MKUserLocation tag]: unrecognized selector sent to instance 0x9fcb010 '

, но мне кажется, что эта вторая ошибка является более простой глупостью с моей стороны, что я по крайней мере знаю, как идти об обнаружении. Но ошибка «class AddressAnnotation» полностью потеряла меня. Любая помощь очень ценится!


Edit:

Привет всем - Спасибо за то, что нашли время, чтобы помочь. Я все еще смущен. Прилагается код для объекта MapData, предложенный Анной Карениной. Verbumdei предположил, что я поместил массив в метод ViewDidLoad в качестве сильного свойства - я играл с этим, но я также хочу иметь возможность обновлять контакты карты массивом, который может иметь больше данных или меньше данных, поэтому мне показалось, что я чтобы каждый раз заново создавать массив. Возможно нет? АннаКаренина предположила, что в MapData может возникнуть проблема с выпуском, и теперь, когда я смотрю на нее, я немного подозрительно, что я не выпускаю тег, но, с другой стороны, это создает предупреждение!

Еще раз спасибо за помощь ... еще не решена.

MapData.h:

#import <Foundation/Foundation.h> 
#import <CoreLocation/CoreLocation.h> 
#import <MapKit/MapKit.h> 

@interface MapData : NSObject <MKAnnotation> 
{ 
    NSString *_title; 
    NSString *subtitle; 
    NSUInteger tag; 
    CLLocationCoordinate2D _coordinate; 
} 

@property (nonatomic, readonly) CLLocationCoordinate2D coordinate; 
@property (nonatomic, copy) NSString *title; 
@property (nonatomic, copy) NSString *subtitle; 
@property(nonatomic) NSUInteger tag; 
// Getters and setters 

- (id)initWithCoordinate:(CLLocationCoordinate2D)c withTag:(NSUInteger)t withTitle:(NSString *)tl withSubtitle:(NSString *)s; 
@end 

и MapData.m:

#import "MapData.h" 

@implementation MapData 

@synthesize coordinate; 
@synthesize title; 
@synthesize subtitle; 
@synthesize tag; 

-(id)initWithCoordinate:(CLLocationCoordinate2D)c withTag:(NSUInteger)t withTitle:(NSString *)tl withSubtitle: (NSString *)s 
{ 
    if(self = [super init]) 
    { 
     coordinate = c; 
     tag = t; 
     title = tl; 
     subtitle = s; 
    } 
    return self;   
} 

- (void) dealloc 
{ 
    [title release]; 
    [subtitle release]; 
    [super dealloc]; 
} 

@end 
+0

Почему вы выпускаете projectMapAnno tationsArray в конце метода showRecordsOnMap? –

+0

Как [документация для addAnnotations] (http://developer.apple.com/library/ios/#DOCUMENTATION/MapKit/Reference/MKMapView_Class/MKMapView/MKMapView.html#//apple_ref/doc/uid/TP40008205-CH3- SW19) говорит, что «вид карты сохраняет отдельные объекты аннотации», поэтому вполне нормально (и вы должны) выпускать projectMapAnnotationsArray. Сбой может быть вызван некоторой проблемой управления памятью в методе init MapData, так что вызов release на mapData вызывает чрезмерный выпуск. Проводка кода метода инициализации MapData может помочь. – Anna

+0

Сообщение об ошибке KVO может быть отдельной проблемой при сбое и из-за неверных координат (см. Http: // stackoverflow.ком/вопросы/5872547/предупреждение в-обычая-карта-аннотаций-iphone? LQ = 1). – Anna

ответ

1

Что касается аварии с EXC_BAD_ACCESS, это, скорее всего, из-за этот код в методе MapData initWithCoordinate:

title = tl; 
subtitle = s; 

инициализации переменного экземпляра таким образом, строки не сохраняются в объекте MapData , Когда вы вызываете [mapData release], строки освобождаются, а затем, когда представление карты пытается получить доступ к заголовку и субтитрам аннотации, он сбой.

Изменение инициализации для:

title = [tl copy]; 
subtitle = [s copy]; 

и ун-прокомментируете [mapData release];


относительно «высвобождены в то время как ключевые наблюдатели значение по-прежнему зарегистрировано ...» предупреждение, это возможно, из-за недействительных координат, используемых для аннотации (см. Warning in Custom Map Annotations iPhone). Для каждой аннотации, убедитесь, что широта от -90 до 90, а долгота от -180 до 180.


Что касается «[MKUserLocation тег]: непризнанные селектор» авария, это не имеет никакого отношения к обоим вышеупомянутых проблем. Эта ошибка возникает, потому что метод делегата viewForAnnotation вызывается видом карты для всех аннотаций - а не только тех, которые вы добавляете. Это означает, что он также призван для синтаксической точки пользователя, которую создает сам вид карты. Это аннотирование местоположения пользователя имеет тип MKUserLocation, а пользовательская аннотация имеет тип MapData. Когда вид карты вызывает viewForAnnotation для местоположения пользователя, этот код выходит из строя, потому что класс MKUserLocation не имеет свойства tag.

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

Кроме того, не изменяйте объявление типа параметра annotation в методе viewForAnnotation в соответствии с вашим пользовательским типом (даже если он «работает»). Как объяснено, метод вызывается для MKUserLocation, а также для вашего пользовательского класса (или классов). Сохраните его тип id<MKAnnotation>, что означает «объект, который реализует протокол MKAnnotation». Затем, чтобы получить доступ к свойствам вашего пользовательского класса, введите annotation в свой собственный тип класса.

Таким образом, верхняя часть метода viewForAnnotation должен быть таким:

- (MKAnnotationView *)mapView:(MKMapView *)mapView 
    viewForAnnotation:(id<MKAnnotation>)annotation 
{ 
    if ([annotation isKindOfClass:[MKUserLocation class]]) 
     return nil; //show standard blue dot view for user location 

Затем измените следующие строки:

if((annotation).tag == 2) annotationView.pinColor = MKPinAnnotationColorRed; 
else annotationView.pinColor = MKPinAnnotationColorGreen; 

к этому:

if ([annotation isKindOfClass:[MapData class]]) 
{ 
    MapData *mapData = (MapData *)annotation; 
    if (mapData.tag == 2) 
     annotationView.pinColor = MKPinAnnotationColorRed; 
    else 
     annotationView.pinColor = MKPinAnnotationColorGreen; 
} 


Есть также несколько других вещей с (не связанные с аварии или ошибки):

  • Этот шаблон является неправильным:

    Record *record = [[[Record alloc] init]autorelease]; 
    record = [currentProject.recordArray objectAtIndex:i]; 
    

    Alloc + INIT + autorelease не имеет смысла, так как переменная затем немедленно переведен на другой объект, который уже выделено. Вместо этого, просто объявить и присвоить локальной переменной:

    Record *record = [currentProject.recordArray objectAtIndex:i]; 
    

    То же самое относится к тому, как title и subtitle устанавливаются таким же способом.

  • showRecordsOnMap, tag всегда 0. Возможно, ваш код еще не закончен, но обязательно укажите другое значение для каждой аннотации. Если вы оставите тег равным нулю для всех аннотаций, код, который вы помещаете в viewForAnnotation, чтобы установить цвет булавки на основе тега, не будет работать должным образом.

  • В этой линии вы передаете title для заголовка и параметров субтитров:

    MapData *mapData =[[MapData alloc] initWithCoordinate:newCoordinate 
        withTag:tag withTitle:title withSubtitle:title]; 
    
  • В viewForAnnotation, после того, как извлечение из существующего вида аннотаций, вы должны обновить annotation свойство представления повторно используется в к тока один (добавить else часть):

    if (annotationView == nil) 
    { 
        annotationView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:record] autorelease]; 
    } 
    else 
    { 
        //We're re-using a view from another annotation 
        //that's no longer on screen. 
        //Update the view's annotation to the current one... 
        annotationView.annotation = annotation; 
    } 
    
+0

Ничего себе! Спасибо, это выглядит очень многообещающе! Я отдам его и отчитаю! – user1976727

+0

Анна Каренина, ты был прав на деньги. Код еще не работает (потому что вы правы: у меня есть нулевые значения в координатах, которые я знаю, как исправить). Другие ошибки также исчезли, и спасибо за подробное объяснение, теперь я также знаю, почему. Цель C очень отличается, чем FORTRAN или BASIC! Ваши другие комментарии также очень полезны. Я нахожусь менее чем в 15 точках, поэтому не могу упрекать вас, но я считаю, что вопрос (очень хорошо) ответил. Спасибо! – user1976727

0

Хотя аннотации показаны на карте, вы не должны освободить объекты MapData. Если вы хотите выпустить объекты MapData, сначала нужно удалить аннотации с карты.

Я предлагаю вам сделать проектMapAnnotationsArray как сильное свойство контроллера вида. Выделите его в методе viewDidLoad. Затем вы можете просто отпустить его в методе dealloc контроллера вида.

Внутри метода showRecordsOnMap вы можете просто добавить объекты в проектMapAnnotationsArray, не выпуская сам массив.

+0

Привет всем - Спасибо, что нашли время, чтобы помочь. – user1976727

Смежные вопросы