does MKAnnotationView buffer its input queue?

后端 未结 1 1085
佛祖请我去吃肉
佛祖请我去吃肉 2020-12-02 01:24

I want to display different colour pins in a UIMapView based on the relative time they represent
but it seems the mapView:viewForAnnotation: method only does it\'s thing

相关标签:
1条回答
  • 2020-12-02 01:47

    There is no guarantee that the viewForAnnotation will be called immediately after addAnnotation or that it will be called only once.

    The annotation could be added in a region that isn't currently visible or the user might pan or zoom the map which causes the annotation to come back into view. The map view will simply call it whenever or as often as it needs to.

    This is by-design and simply how the delegate method approach works.

    For this reason, your implementation of the delegate method should generally only use the annotation parameter passed to the method as the basis for all the logic inside the method. It should not rely on any external variables or make broad assumptions about when it will be called.

    For other answers that may explain this in more detail, see:

    • Map view annotations with different pin colors
    • MKMapview annotation dynamic pin image changes after zooming
    • Map annotation display all the same image/pins for all points
    • Setting Map Pin colour dynamically for iOS, etc

    For your question specifically, I suggest the following:

    1. Right now you're adding annotations of type MKPointAnnotation which don't contain the "age" information that the viewForAnnotation method needs (I'm assuming this is what it needs).

      Instead of using MKPointAnnotation, make your Finding class (or whatever the type is of the self.finding object) implement the MKAnnotation protocol itself. You should be able to find several examples of custom annotation classes on SO.

      Then, instead of keeping an annotationFlag variable and creating MKPointAnnotation objects, add the Finding objects themselves (which contain their "age") directly to the map when calling addAnnotation.

    2. In viewForAnnotation, set the pinColor after the if-else that creates/dequeues the view and just before the return. Be sure to set the pinColor based on the age property of the annotation object passed into the method (which will be a Finding type object). For example:

      - (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id)annotation 
      {
          if([annotation isKindOfClass:[MKUserLocation class]])
              return nil;
      
          static NSString *identifier = @"myAnnotation";
          MKPinAnnotationView * annotationView = (MKPinAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:identifier];
          if (!annotationView)
          {
              annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:identifier];
              annotationView.animatesDrop = YES;
              annotationView.canShowCallout = NO;
              annotationView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeSystem];
          }else {
              annotationView.annotation = annotation;
          }
      
          //update the pinColor in the view whether it's a new OR dequeued view...
          if ([annotation isKindOfClass:[Finding class]])
          {
              Finding *f = (Finding *)annotation;
      
              if ([f.age isEqualToString:@"2"]) {
                  annotationView.pinColor = MKPinAnnotationColorGreen;
              }
              else if ([f.age isEqualToString:@"1"]) {
                  annotationView.pinColor = MKPinAnnotationColorPurple;
              }
              else {
                  annotationView.pinColor = MKPinAnnotationColorRed;
              }
          }
      
          return annotationView;
      }
      
    0 讨论(0)
提交回复
热议问题