2012-04-15 9 views
2

Ich habe etwas seltsam gefunden, vielleicht ist das jedem bekannt: Ich füge eine einfache MKPointAnnotation zu einem MKMapView, dann seine Koordinaten-Eigenschaft mit KVO-Compliance ändern, dann entfernen Sie die Anmerkung mit -removeAnnotation:. Wenn ich jedoch nach dem Löschen der Annotation die Map verschiebe, tritt die Pin wieder auf - obwohl die Annotation angeblich entfernt wurde! Bei genauerer Betrachtung scheint MKMapView die Annotation nicht wirklich entfernt zu haben.MKMapView Annotation nicht richtig entfernen?

Bitte beachten Sie das folgende Code-Snippet. Sie können es in ein neues Xcode iOS-Projekt einfügen, eine einzelne Ansicht reicht aus. Fügen Sie der Ansicht eine MKMapView hinzu, dann 3 Schaltflächen Start, Schritt, Stop, und verbinden Sie sie mit den entsprechenden Aktionen. "userAnnotation" ist ein MKPointAnnotation-Ivar im View-Controller. Wenn Sie Stopp drücken, wird die Anzahl der Anmerkungen von MKMapView vor und nach dem Entfernen auf die Konsole gedruckt. ARC ist aktiviert.

Wie zu reproduzieren:

  1. Press Start; Ein Pin erscheint.
  2. Drücken Sie Schritt; Der Pin bewegt sich ein wenig.
  3. Drücken Sie Stop; Der Stift verschwindet.
  4. Ziehen Sie die Karte - der Pin erscheint wieder!

Wenn Sie Start und dann Stop drücken (nicht Step drücken), wird die Annotation korrekt entfernt, überprüfen Sie den Zähler in der Konsole: 1, 1 = komisch; 1, 0 = ok

Irgendeine Idee, was passiert? Ich dachte, ich hätte das KVO-Ding richtig gemacht.

- (IBAction)startTouched:(id)sender 
{ 
    userAnnotation = [[MKPointAnnotation alloc] init]; 
    userAnnotation.coordinate = CLLocationCoordinate2DMake(50.85, 4.72); // some coord 
    [mapView addAnnotation:userAnnotation]; 

    MKMapPoint p = MKMapPointForCoordinate(userAnnotation.coordinate); 
    double w = 500 * MKMapPointsPerMeterAtLatitude(userAnnotation.coordinate.latitude); 
    [mapView setVisibleMapRect:MKMapRectMake(p.x - w, p.y - w, 2*w, 2*w) animated:NO]; 
} 

- (void)nextLocation 
{ 
    MKMapPoint p = MKMapPointForCoordinate(userAnnotation.coordinate); 
    p.x += 10 * MKMapPointsPerMeterAtLatitude(userAnnotation.coordinate.latitude); 

    [userAnnotation willChangeValueForKey:@"coordinate"]; 
    userAnnotation.coordinate = MKCoordinateForMapPoint(p); 
    [userAnnotation didChangeValueForKey:@"coordinate"]; 

    NSLog(@"pin at %@, %@", MKStringFromMapPoint(p), [NSThread currentThread]); 
} 

- (IBAction)stepTouched:(id)sender 
{ 
    [self nextLocation]; 
} 

- (IBAction)stopTouched:(id)sender 
{ 
NSLog(@"mark 10, map has %u annotations, %@", [mapView.annotations count], userAnnotation); 
    [mapView removeAnnotation:userAnnotation]; 
NSLog(@"mark 20, map has %u annotations, %@", [mapView.annotations count], [NSThread currentThread]); 
    userAnnotation = nil; 
} 

Antwort

3

Ich bin mir nicht sicher, was genau das Problem ist, aber Sie wahrscheinlich nicht brauchen, manuelle KVO Benachrichtigungen (dh willChangeValueForKey:/didChangeValueForKey :) wie dass, wenn Sie einen Setter verwenden (was Sie sind; userAnnotation.coordinate = ... ist nur [userAnnotation setCoordinate:...]).

Versuchen Sie, die WillChange/DidChange entfernen und sehen, ob das Dinge verbessert?

+0

Wow, danke Jesse! Es scheint zu funktionieren! Daher müssen wir KVO-Methoden nur verwenden, wenn wir einen eigenen Setter für die Koordinateneigenschaft haben. Ahhhhh. – bio

+0

@bio Wenn Sie einen Setter der richtigen Form verwenden (setCoordinate: in diesem Fall), müssen Sie die KVO-Methoden nicht manuell verwenden. Nur wenn Sie den ivar direkt einstellen, müssen Sie die Benachrichtigungen verwenden. (Oder wenn Sie die automatische Benachrichtigung deaktivieren.) –