Optimizing Code for MKMapView - Large Number of Annotations

后端 未结 2 521
别跟我提以往
别跟我提以往 2020-12-25 09:11

I have a modal view in my app which displays a UIMapView. I then add a large number of annotations (over 800) to this map view (code below).

The problem is that the

相关标签:
2条回答
  • 2020-12-25 09:27

    I completely agree with Anna. But consider that 800 AnnotationViews at the same time will result in a extreme laggy interface. So if your map should provide user interaction like scrolling or zooming you better implement some kind clustering of your annotation views.

    0 讨论(0)
  • 2020-12-25 09:42

    The two biggest speed improvements you can make here are:

    • Implement annotation view re-use (right now it creates a new view every time it needs to show an annotation even if the same one comes into view again.
    • Change how the UniqueID is set. To set it, the code is currently looping through all the annotations every time it creates an annotation view (which could happen any time the map view is zoomed or scrolled--not just the initial time).

    First, instead of searching for the UniqueID in the viewForAnnotation method and using a button tag to pass the annotation identifier, add UniqueID as a property to your custom annotation class MyLocation and set the property when you add the annotation itself in addPins:

    annotation.uniqueID = info.UniqueID;  // <-- give id to annotation itself
    [mapViewLink addAnnotation:annotation];     
    

    You could also add uniqueID as a parameter to the initWithName method instead of assigning the property separately.


    Next, to implement annotation view re-use, the viewForAnnotation method should look like this:

    - (MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>) annotation{
    
        if (annotation == mapView.userLocation){
            return nil; //default to blue dot
        }    
    
        NSString *reuseId = @"StandardPin";
        MKPinAnnotationView *annView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:reuseId];
        if (annView == nil)
        {
            annView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:reuseId] autorelease];
    
            annView.pinColor = MKPinAnnotationColorRed;
            annView.animatesDrop = YES;
            annView.canShowCallout = YES;
            annView.calloutOffset = CGPointMake(-5, 5);
    
            UIButton *advertButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
            advertButton.frame = CGRectMake(0, 0, 23, 23);
            advertButton.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
            advertButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
    
            annView.rightCalloutAccessoryView = advertButton;
        }
        else
        {
            //update the annotation property if view is being re-used...
            annView.annotation = annotation;
        }
    
        return annView;
    }
    


    Finally, to respond to the button press and figure out which UniqueID to show the detail for, implement the calloutAccessoryControlTapped delegate method:

    - (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view 
                calloutAccessoryControlTapped:(UIControl *)control
    {
        MyLocation *myLoc = (MyLocation *)view.annotation;
    
        int uniqueID = myLoc.uniqueID;
    
        NSLog(@"calloutAccessoryControlTapped, uid = %d", uniqueID);
    
        //create, init, and show the detail view controller here...
    }
    


    After all these changes, only the initial loading of the annotations will take up most of the time. If that is still a problem, one solution is to only add annotations that would be visible in the currently displayed region and add/remove annotations as the user changes the visible region.

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