Сбой с непризнанным селектором, когда пользователь прикасается к аннотации

У меня есть приложение для отображения карты и пользовательской аннотации. Мое приложение вылетает, когда пользователь коснется аннотации. Это происходит только в iOS 7. Он отлично работает с iOS 6 и iOS 5.

Ниже приведен отчет о сбое, который отображается в консоли:

ERROR: Trying to select an annotation which has not been added
-[__NSSetM coordinate]: unrecognized selector sent to instance 0x18c9d580
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSSetM coordinate]: unrecognized selector sent to instance 0x18c9d580'
*** First throw call stack:
(
    0   CoreFoundation                      0x020415e4 __exceptionPreprocess + 180
    1   libobjc.A.dylib                     0x016918b6 objc_exception_throw + 44
    2   CoreFoundation                      0x020de903 -[NSObject(NSObject) doesNotRecognizeSelector:] + 275
    3   CoreFoundation                      0x0203190b ___forwarding___ + 1019
    4   CoreFoundation                      0x0206e46e __forwarding_prep_1___ + 14
    5   MapKit                              0x000de10c _Z21_insertionNodeForItemP11objc_objectP14MKQuadTrieNode + 50
    6   MapKit                              0x000de428 _Z9_containsP11objc_objectP14MKQuadTrieNode + 27
    7   MapKit                              0x000de8ed -[MKQuadTrie contains:] + 39
    8   MapKit                              0x000d4918 -[MKAnnotationManager selectAnnotation:animated:avoid:] + 116
    9   MapKit                              0x00090789 -[MKMapView handleTap:] + 541
    10  UIKit                               0x0056ae8c _UIGestureRecognizerSendActions + 230
    11  UIKit                               0x00569b00 -[UIGestureRecognizer _updateGestureWithEvent:buttonEvent:] + 383
    12  UIKit                               0x0056b56d -[UIGestureRecognizer _delayedUpdateGesture] + 60
    13  UIKit                               0x0056eacd ___UIGestureRecognizerUpdate_block_invoke + 57
    14  UIKit                               0x0056ea4e _UIGestureRecognizerRemoveObjectsFromArrayAndApplyBlocks + 317
    15  UIKit                               0x00565148 _UIGestureRecognizerUpdate + 199
    16  CoreFoundation                      0x020094ce __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 30
    17  CoreFoundation                      0x0200941f __CFRunLoopDoObservers + 399
    18  CoreFoundation                      0x01fe7344 __CFRunLoopRun + 1076
    19  CoreFoundation                      0x01fe6ac3 CFRunLoopRunSpecific + 467
    20  CoreFoundation                      0x01fe68db CFRunLoopRunInMode + 123
    21  GraphicsServices                    0x01f6c9e2 GSEventRunModal + 192
    22  GraphicsServices                    0x01f6c809 GSEventRun + 104
    23  UIKit                               0x001f2d3b UIApplicationMain + 1225
    24  CustomMKAnnotationView              0x0000285a main + 170
    25  CustomMKAnnotationView              0x000027a5 start + 53
)
libc++abi.dylib: terminating with uncaught exception of type NSException

И я создал код следующим образом:

-(void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view
{
    if ([view.annotation isKindOfClass:[BasicMapAnnotation class]])
        {
        if (_calloutAnnotation.coordinate.latitude == view.annotation.coordinate.latitude&&
            _calloutAnnotation.coordinate.longitude == view.annotation.coordinate.longitude)
        {
            return;
        }
        if (_calloutAnnotation)
        {
            [mapView removeAnnotation:_calloutAnnotation];
            _calloutAnnotation = nil;
        }
        _calloutAnnotation = [[[CalloutMapAnnotation alloc] 
                               initWithLatitude:view.annotation.coordinate.latitude
                              andLongitude:view.annotation.coordinate.longitude]autorelease];
        [mapView addAnnotation:_calloutAnnotation];

        [mapView setCenterCoordinate:_calloutAnnotation.coordinate animated:YES];
    }else
    {
        if([delegate respondsToSelector:@selector(customMKMapViewDidSelectedWithInfo:)])
        {
            [delegate customMKMapViewDidSelectedWithInfo:@"Annotation clicked"];
        }
    }
}

-(void)mapView:(MKMapView *)mapView didDeselectAnnotationView:(MKAnnotationView *)view 
    {
    if (_calloutAnnotation&& ![view isKindOfClass:[CallOutAnnotationVifew class]])
    {
        if (_calloutAnnotation.coordinate.latitude == view.annotation.coordinate.latitude&&
            _calloutAnnotation.coordinate.longitude == view.annotation.coordinate.longitude)
        {
            [mapView removeAnnotation:_calloutAnnotation];
            _calloutAnnotation = nil;
        }
    }
}

-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
    if ([annotation isKindOfClass:[CalloutMapAnnotation class]])
    {

        CallOutAnnotationVifew *annotationView = (CallOutAnnotationVifew *)[mapView     dequeueReusableAnnotationViewWithIdentifier:@"CalloutView"];
        if (!annotationView)
        {
            annotationView = [[[CallOutAnnotationVifew alloc] initWithAnnotation:annotation reuseIdentifier:@"CalloutView"] autorelease];
            JingDianMapCell  *cell = [[[NSBundle mainBundle] loadNibNamed:@"JingDianMapCell" owner:self options:nil] objectAtIndex:0];
            cell.titleLable.text = @"Testing";
            [annotationView.contentView addSubview:cell];

        }
        return annotationView;
    }else if ([annotation isKindOfClass:[BasicMapAnnotation class]])
    {

         MKAnnotationView *annotationView =[self.mapView dequeueReusableAnnotationViewWithIdentifier:@"CustomAnnotation"];
        if (!annotationView)
        {
            annotationView = [[[MKAnnotationView alloc] initWithAnnotation:annotation 
                                                           reuseIdentifier:@"CustomAnnotation"] autorelease];
            annotationView.canShowCallout = NO;
            annotationView.image = [UIImage imageNamed:@"pin.png"];
        }

        return annotationView;
    }
    return nil;
}

В didSelectAnnotationView и didDeselectAnnotationView Я добавляю новое представление аннотации и удаляю старый аннотационный вид. Представление аннотации - это пользовательский класс. И _calloutAnnotation - это объект CalloutMapAnnotation, который является классом NSObject для добавления аннотации.

Ответ 1

_calloutAnnotation не содержит аннотаций. Я думаю, что у вас есть код вроде этого @prorerty (weak, nonatomic) MKAnnotation * calloutAnnotation;, изменяющий weak на strong, должен помочь.

Ответ 2

Марчин частично прав. Однако основная идея заключается в ERROR: Trying to select an annotation which has not been added Что здесь происходит, так это то, что пользователь нажимает "пузырь вызова", который на самом деле представляет собой аннотацию. Как часть этого, MapView сначала отменяет выбранную аннотацию, а затем выбирает аннотацию, которую пользователь нажал. Однако, поскольку вы уже удалили выбранную аннотацию из карты на этапе удаления, ничего не нужно выбирать. Следовательно, сообщение "ERROR..." в отладчике.
-(void)mapView:(MKMapView *)mapView didDeselectAnnotationView:(MKAnnotationView *)view 
{
  if (_calloutAnnotation&& ![view isKindOfClass:[CallOutAnnotationVifew class]])
  {
    if (_calloutAnnotation.coordinate.latitude == view.annotation.coordinate.latitude&&
        _calloutAnnotation.coordinate.longitude == view.annotation.coordinate.longitude)
    {
        CalloutMapAnnotation *oldAnnotation = self.calloutAnnotation; //saving it to be removed from the map later
        self.calloutAnnotation = nil; //setting to nil to know that we aren't showing a callout anymore
        dispatch_async(dispatch_get_main_queue(), ^{
            [mapView removeAnnotation:oldAnnotation]; //removing the annotation a bit later
        });
    }
  }
}

Ответ 3

Ваша проблема здесь:

-(void)mapView:(MKMapView *)mapView didDeselectAnnotationView:(MKAnnotationView *)view 
    {
    if (_calloutAnnotation&& ![view isKindOfClass:[CallOutAnnotationVifew class]])
    {
        if (_calloutAnnotation.coordinate.latitude == view.annotation.coordinate.latitude&&
            _calloutAnnotation.coordinate.longitude == view.annotation.coordinate.longitude)
        {
            [mapView removeAnnotation:_calloutAnnotation];
//EDIT: This code is broken don't use it :)
            //in iOS7.0 responder chain is changed a bit and you can't call this directly give it some time or remove this line and your crash will be gone ;)
//            double delayInSeconds = 0.5;
//        dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
//        dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
//            _calloutAnnotation = nil;
//        });
        }
    }
}