E 'possibile spostare le coordinate di un MKAnnotation senza aggiungere e rimuovere l'annotazione dalla mappa?
Come spostare un MKAnnotation senza aggiungere / rimuovere dalla mappa?
Ho trovato un metodo piuttosto semplice. Ho voluto aggiornare la posizione del lettore senza problemi, senza rimuovere e poi ri-aggiungendo il giocatore annotazione. Questo funziona bene per i pre-iOS4 apps, e ciò che fa è sia spostare il perno e il centro della mappa su nuova posizione della spina:
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
[UIView setAnimationCurve:UIViewAnimationCurveLinear];
[player setCoordinate:aLoc.coordinate];
[mapView setCenterCoordinate:aLoc.coordinate animated:NO];
[UIView commitAnimations];
Ecco la stessa cosa, ma utilizzando la funzione di blocco raccomandato per iOS4:
[UIView animateWithDuration:0.5 animations:^{
[player setCoordinate:aLoc.coordinate];
[mapView setCenterCoordinate:aLoc.coordinate animated:NO];
}];
È infatti possibile senza rimuovere e aggiungendo l'annotazione fuori rotta.
Avrai bisogno di osservare il vostro MKAnnotation di coordinate e aggiornare la posizione del MKAnnotationView quando cambia. In alternativa si può (e questo è probabilmente il più elegante modo di farlo) derivare il proprio MKAnnotation e MKAnnotationView e renderli "mobile".
Vedere Moving-MKAnnotationView per un esempio dettagliato che anima anche la posizione dell'annotazione.
Sottoclasse MKPointAnnotation ed ha la capacità di aggiornare la vista annotazione sulla mappa per la nuova coordinata automaticamente.
Basta usare KVO:
[annotation willChangeValueForKey:@"coordinate"];
[annotation didChangeValueForKey:@"coordinate"];
Se il vostro MKAnnotation ha un metodo setCoordinate, è sufficiente includere queste righe proprio lì:
- (void)setCoordinate:(CLLocationCoordinate2D)newCoordinate {
[self willChangeValueForKey:@"coordinate"];
coordinate = newCoordinate;
[self didChangeValueForKey:@"coordinate"];
}
Non so se è più in generale possibile, ma è se avete il vostro MKAnnotationView personalizzato.
Sono stato in grado di adattare l'approccio documentato in http://spitzkoff.com/craig/?p=108 da Craig Spitzkoff:
- Lascia la tua personalizzato MKAnnotationView un riferimento all'oggetto MKAnnotation
- Aggiungere un metodo updateCoordinates all'oggetto MKAnnotation e chiamarlo quando si desidera modificare la posizione dell'annotazione
- Chiamare regionChanged sul MKAnnotationView personalizzato per lasciarlo sapere quando riposizionarsi (ad esempio quando MKAnnotation ha aggiornato coordinate)
- Nel drawRect sull'oggetto vista interna di proprietà della vostra abitudine MKAnnotationView è possibile riposizionare usando le coordinate del MKAnnotation (siete in possesso di un riferimento ad esso).
Si potrebbe probabilmente semplificare ulteriormente questo approccio - non si può richiedere una vista oggetto interno in tutte le circostanze.
Dopo aver aggiornato le coordinate o alcune altre proprietà del annotazioni, basta chiamare seguente metodo MKMapViewDelegate di ridisegnare l'annotazione:
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation;
per esempio:
myAnnotation.coordinate = CLLocationCoordinate2DMake([newLat doubleValue], [newLon doubleValue]);
[self mapView:self.mapView viewForAnnotation:myAnnotation];
La maggior parte delle risposte si basano sul fatto che la vostra annotazione è stata fatta tramite l'estensione MKPlacemark. Ma che dire di qualsiasi altro oggetto (immagine cioè su misura per il marcatore), che implementa solo il protocollo MKAnnotation? Non avrebbe il metodo di setCoordinate. Quindi, ecco la risposta basato sul codice, fornito da 100grams
MKAnnotationView *av = [self.mapView viewForAnnotation:user];
//user is an object which implements <MKAnnotation>
// You will probably get your MKAnnotationView in your own way
if (av){
// here user returns CLLocationCoordinate2D coordinate
MKMapPoint mapPoint = MKMapPointForCoordinate([user getLastLocation]);
// converting mapPoint to CGPoint
CGPoint newPos;
CGFloat zoomFactor = self.mapView.visibleMapRect.size.width / self.mapView.bounds.size.width;
newPos.x = mapPoint.x/zoomFactor;
newPos.y = mapPoint.y/zoomFactor;
// animation for annotation's move
static NSString *POSITION_KEY=@"positionAnimation";
static NSString *PATH_ANIMATION_KEY=@"position";
if (MKMapRectContainsPoint(self.mapView.visibleMapRect, mapPoint)) {
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:PATH_ANIMATION_KEY];
animation.fromValue = [NSValue valueWithCGPoint:av.center];
animation.toValue = [NSValue valueWithCGPoint:newPos];
animation.duration = 0.3;
animation.delegate = av;
animation.fillMode = kCAFillModeForwards;
[av.layer addAnimation:animation forKey:POSITION_KEY];
}
// moving view
av.center = newPos;
Che, fondamentalmente, così necessario per ottenere il corrispondente MKAnnotationView che potrebbe essere raggiunto anche per iterazione attraverso tutti annotazioni ed è nuova posizione. Feci un titolare di array per tutto questo (NSMutableArray * mapAnnotaions), così ora ho potuto scorrere proprio come:
for (id annotation in mapAnnotaions) {call refresh method here for id}
Se si mantiene un riferimento alla vostra annotazione, apportare una modifica alla proprietà di coordinate, quindi aggiungere l'annotazione di nuovo la mappa, la posizione del vista annotazione verrà aggiornato. Non è necessario rimuovere l'annotazione (che causerà la vista annotazione di scomparire momentaneamente). Questo non vi darà una bella transizione per quando coordinate viene aggiornato tuttavia l'annotazione. Inoltre non si traduca in una perdita di memoria, né ci sono un multiplo dello stesso annotazioni aggiunti alla mappa (se si guarda al numero di annotazioni sul mapview, rimane costante quando si ri-aggiunge l'annotazione).
In Swift 4.0 e IOS 11.0, ho appena aggiungo attributo dinamico alla proprietà coordinata classe figlio di classe MKAnnotation e funziona: tutte le annotazioni su MapView aggiornare la loro posizione se coordinare valore degli oggetti MKAnnotation vengono aggiornati:
class CarAnnotation: NSObject, MKAnnotation {
@objc dynamic var coordinate: CLLocationCoordinate2D
//Add your custom code here
}
Date un'occhiata al mio MapKitDragAndDrop campione, consente di aggiornare MKAnnotation e sposta MKAnnotationView sia su iPhone OS 3 e iOS 4 (utilizzerà un supporto integrato trascinamento).
Non sembra possibile cambiare le coordinate di un oggetto MKAnnotation e poi informare il MKMapView del cambiamento.
Tuttavia, la rimozione l'annotazione precedente dalla mappa, cambiando le coordinate del vostro oggetto di annotazione e l'aggiunta di nuovo alla mappa funziona bene.
[theMapView removeAnnotation:myAnnotation];
[myAnnotation setLatitude:newLatitude];
[theMapView addAnnotation:myAnnotation];
Perché non si vuole fare in questo modo?













