Аннотации MKMapView меняют / теряют порядок? - PullRequest
6 голосов
/ 03 марта 2012

У меня есть вид карты с аннотациями, и эти аннотации отображают выноску. Когда нажимается кнопка раскрытия информации выноски, она переходит в новый вид.

Мои MKAnnotations - это пользовательский класс, который реализует <MKAnnotation>. Давайте назовем этот класс MyClass. Они хранятся в NSMutableArray. Во время просмотра этого представления я добавляю каждый объект MyClass в этом массиве к аннотациям представления карты. Используя отладчик, я вижу, что после того, как все это добавление выполнено, порядок [self.MapView annotations] совпадает с NSMutableArray.

Теперь я устанавливаю другую точку останова в mapView: viewForAnnotation: и проверяю порядок 1) моего NSMutableArray и 2) [self.MapView annotations]. Массив, конечно, в том же порядке. Однако порядок аннотаций был зашифрован.

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

Теперь я понял, что могу просто сохранить аннотацию напрямую (исходя из фона Android, это было очень круто для меня). Тем не менее, я до сих пор концептуально не понимаю, почему заказ стал зашифрованным. Кто-нибудь может мне помочь? Код ниже:

- (void)viewDidLoad
{


    if([fromString isEqualToString:@"FromList"])
        self.navigationItem.hidesBackButton = TRUE;
    else { 
        self.navigationItem.rightBarButtonItem = nil;
    }


    self.array = [MySingleton getArray];
    //set up map

    //declare latitude and longitude of map center
    CLLocationCoordinate2D center;
    center.latitude = 45;
    center.longitude = 45;

    //declare span of map (height and width in degrees)
    MKCoordinateSpan span;
    span.latitudeDelta = .4;
    span.longitudeDelta = .4;

    //add center and span to a region, 
    //adjust the region to fit in the mapview 
    //and assign to mapview region
    MKCoordinateRegion region;
    region.center = center;
    region.span = span;
    MapView.region = [MapView regionThatFits:region];

    for(MyClass *t in self.array){
        [MapView addAnnotation:t];
    }
    [super viewDidLoad];
}



//this is the required method implementation for MKMapView annotations
- (MKAnnotationView *) mapView:(MKMapView *)thisMapView 
             viewForAnnotation:(MyClass *)annotation
{


    static NSString *identifier = @"MyIdentifier";

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

    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;

    UIButton *infoButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
    annotationView.rightCalloutAccessoryView = infoButton;


    return annotationView;
}

Ответы [ 2 ]

7 голосов
/ 03 марта 2012

Когда вы звоните addAnnotation или addAnnotations, представление карты добавляет ссылку (и) в свой внутренний список аннотаций.

Свойство annotations MKMapView просто возвращает этот внутренний список (каким бы он ни был) как NSArray.

Я не знаю ни одного места в документации, где говорится, что свойство annotations возвращает массив в том же порядке, в котором вы добавили аннотации. Если вы включили showsUserLocation, массив будет включать эта аннотация, даже если вы не добавили ее явно.

Вам не нужно беспокоиться и не следует зависеть от порядка объектов в свойстве annotations.

Несколько предложений по коду:

  • Поскольку ваш array содержит объекты, которые реализуют <MKAnnotation>, вместо того, чтобы зацикливаться на нем, вы можете добавить все аннотации в одном кадре, вызвав addAnnotations (множественное число) и передав ему массив
  • В viewForAnnotation ни одно из настраиваемых свойств не зависит от какой-либо конкретной аннотации, поэтому вы можете установить их все внутри блока if (av == nil). Таким образом, вы получите максимальное повторное использование.
  • Также в viewForAnnotation, после и за пределами if, вы должны установить для свойства annotation представления текущую аннотацию. Это в случае, если представление повторно используется из другой аннотации.
  • Наконец, в viewForAnnotation не думайте, что annotation будет иметь тип MyClass. Если вы включите showsUserLocation, этого не произойдет. Безопаснее объявить параметр как id<MKAnnotation>, а затем при необходимости проверить его класс и затем привести его.
1 голос
/ 12 февраля 2013

@ Анна, вы заявляете, что не должны беспокоиться о порядке аннотаций. Это не правда в моем случае. Некоторые аннотации могут накладываться друг на друга, и мне всегда нужно, чтобы конкретный вид был сверху двух перекрывающихся видов. Так что порядок DO имеет смысл для аннотаций, так как я надеюсь, что - (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation вызывается в том же порядке, в котором я добавил аннотации.

EDIT: и решение здесь: -)

...