Brian Ross
Brian Ross

Reputation: 71

Sequential plotting and display of MKMapAnnotations on MKMapView

I have an Array of map annotations that I want to add to an MKMapView. I would like to be able to add them one at a time with a short pause between each add, so I can show the progress of a past journey. In looking at the MKMapView component, I see two methods:

[self.mapView addAnnotation: ann];

and

[self.mapView addAnnotations: annArray];

Using the array blasts them all out there at the same time, so I tried a looping process trying to render each annotation like so

    for (MapAnnotation *ann in _MapAnnotations) {
        //Add custom annotation to map
        [self.mapView addAnnotation: ann];

        //pause for 0.25 seconds
        usleep(250000);
    }

This does not work either - the process pauses alright, but no rendering is done until all points are plotted. I tried using the mapView setNeedsDisplay statement to force the rendering of the map, but no luck. Any ideas?

Thanks to Duncan, my code now looks like this, but I am getting crashes when I try and scroll away during the population, any ideas?

View level variable

@private BOOL userScrolling;

scroll button

//Next Day Clicked
- (IBAction)btnNext:(id)sender{
    //Move forward one day
    userScrolling = YES;
    [self setTheDate: 1];
}

plotting code

    userScrolling = NO;


    [_MapAnnotations enumerateObjectsUsingBlock: ^(id object,
                                                   NSUInteger index,
                                                   BOOL *stop)
     {
         if (userScrolling){ *stop = YES;}

         dispatch_after(dispatch_time(DISPATCH_TIME_NOW,
                                      (int64_t)( index * 0.25 * NSEC_PER_SEC)),
                        dispatch_get_main_queue(), ^
                        {
                            if (!userScrolling){
                                MapAnnotation *ann = _MapAnnotations[index];
                                [self.mapView addAnnotation: ann];
                                [self.mapView setNeedsDisplay];
                            }else{
                                *stop = YES;
                            }

                        }
                        );}];

Upvotes: 0

Views: 41

Answers (1)

Duncan C
Duncan C

Reputation: 131418

Never, ever, EVER use sleep on your app's main thread. That locks up the UI, and prevents anything from happening. If you sleep the main thread for more than a few seconds the system will kill your app, thinking it's hung.

Instead, use dispatch_after to add a delay between calls:

[_MapAnnotations enumerateObjectsUsingBlock: ^(id object, 
  NSUInteger index, 
  BOOL *stop)
  {
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 
      (int64_t)( index * 0.25 * NSEC_PER_SEC)), 
      dispatch_get_main_queue(), ^
    {
      [self.mapView addAnnotation: ann];
    }
  }
];

That code loops through your array of annotations, adding each one after a delay value starting at 0 and going up by .25 second intervals.

Upvotes: 1

Related Questions