Refresh MKAnnotationView on a MKMapView

前端 未结 7 463
天涯浪人
天涯浪人 2021-01-31 09:27

I\'d like to a-synchronically load images for my custom MKAnnotationView; I\'m already using the EGOImageView-framework (it goes very well with UITableViews), but I fail to make

相关标签:
7条回答
  • 2021-01-31 09:41

    I found only one reliable way to update annotation, others methods didn't work for me: just removing and adding annotation again:

    id <MKAnnotation> annotation;
    
    // ...
    
    [mapView removeAnnotation:annotation];
    [mapView addAnnotation:annotation];
    

    This code will make -[mapView:viewForAnnotation:] to be called again and so your annotation view will be created again (or maybe reused if you use dequeueReusableAnnotationViewWithIdentifier) with correct data.

    0 讨论(0)
  • 2021-01-31 09:44

    (I don't see how to indicate that this post pertains to zerodiv's answer.) I was able to get zerodiv's method to work by adding a kickstart of sorts, forcing a meaningless but different coordinate, then restoring the prior, correct one. The screen doesn't flash at all because of the first location.

    CLLocationCoordinate2D center = mapView.centerCoordinate; 
    CLLocationCoordinate2D forceChg;
    forceChg.latitude = 0;
    forceChg.longitude = curLongNum;
    
    mapView.centerCoordinate = forceChg;
    mapView.centerCoordinate = center;
    
    0 讨论(0)
  • 2021-01-31 09:47

    Thank you @Vladimir for the help! Your answer inspired my answer. I made some changes to make it clearer.

    func addAnnotation(coordinate: CLLocationCoordinate2D) {
        let annotation = Annotation()
        annotation.coordinate = coordinate
        annotations.append(annotation)
        mapView.addAnnotation(annotation)
        for index in 0..<annotations.count {
            if let view = mapView.view(for: annotations[index]) as? AnnotationView {
                if index == 0 {
                    view.imageView.image = NSImage(named: "icon_positioning")
                } else {
                    view.imageView.image = NSImage(named: "icon_positioning")
                }
            }
        }
    }
    

    Also the protocol in MKMapview needs to implement:

    func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
        let view = mapView.dequeueReusable(withClass: AnnotationView.self, annotation: annotation)
        if index == 0 {
            view.imageView.image = NSImage(named: "icon_positioning")
        } else {
            view.imageView.image = NSImage(named: "icon_positioning")
        }
        return view
    }
    

    By the way, the AnnotationView initialization here is:

    public extension MKMapView {
        func dequeueReusable<T: MKAnnotationView>(withClass name: T.Type,annotation: MKAnnotation?) -> T {
            if let view = dequeueReusableAnnotationView(withIdentifier: T.identifier()) as? T {
                return view
            }
            let view = T.init(annotation: annotation, reuseIdentifier: T.identifier())
            return view
        }
    }
    

    Thanks again @Vladimir for the answer

    0 讨论(0)
  • 2021-01-31 09:48

    This is the only way I've found to force redraw of MKAnnotationViews:

    // force update of map view (otherwise annotation views won't redraw)

    CLLocationCoordinate2D center = mapView.centerCoordinate;

    mapView.centerCoordinate = center;

    Seems useless, but it works.

    0 讨论(0)
  • 2021-01-31 09:50

    I wanted to refresh user location pin with new selected avatar. I found another fast solution for that case. I have 2 screens. The first one is for selecting avatar and the second is for displaying user on map.

    swift 5 You can change user location image by creating MKAnnotationView

    func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
    
        if annotation is MKUserLocation {
            let userIdentifier = "UserLocation"
            var userView = mapView.dequeueReusableAnnotationView(withIdentifier: userIdentifier)
            if userView == nil {
                userView = MKAnnotationView(annotation: annotation, reuseIdentifier: userIdentifier)
            } else {
                userView?.annotation = annotation
            }
    
            userView!.image = UIImage(named: "avatar1") //your image
    
            return userView
        }
    
        return nil
     }
    

    So if user will change avatar to something else, for example to "avatar2" it won't refresh.

    In order to refresh user location image i added this code in viewWillAppear()

     self.mapView.showsUserLocation = false
     self.mapView.showsUserLocation = true
    
    0 讨论(0)
  • 2021-01-31 10:03

    I haven't tried it myself, but it might work:
    Get a view for annotation using MKMapView - (MKAnnotationView *)viewForAnnotation:(id <MKAnnotation>)annotation method and set new image to it.

    Edit: Tried to do that myself and this approach worked fine for me:

    //  Function where you got new image and want to set it to annotation view
    for (MyAnnotationType* myAnnot in myAnnotationContainer){
        MKAnnotationView* aView = [mapView viewForAnnotation: myAnnot];
        aView.image = [UIImage imageNamed:@"myJustDownloadedImage.png"];
    }
    

    After calling this method all annotations images were updated.

    0 讨论(0)
提交回复
热议问题