Trying to simulate a route in MapView

偶尔善良 提交于 2019-12-09 04:53:21

问题


I have an array of CLLocation objects I parsed from a file. I'd want to simulate that the user is moving along that route, and I have implemented this:

for (CLLocation *loc in simulatedLocs) {
            [self moveUser:loc];
            sleep(1);
        }

This is the method called in the loop:

- (void)moveUser:(CLLocation*)newLoc
{
    CLLocationCoordinate2D coords;
    coords.latitude = newLoc.coordinate.latitude;
    coords.longitude = newLoc.coordinate.longitude;
    CustomAnnotation *annotation = [[CustomAnnotation alloc] initWithCoordinate:coords];
    annotation.title = @"User";

    // To remove the previous location icon
    NSArray *existingpoints = self.mapView.annotations;
    if ([existingpoints count] > 0) {
        for (CustomAnnotation *annotation in existingpoints) {
            if ([annotation.title isEqualToString:@"User"]) {
                [self.mapView removeAnnotation:annotation];
                break;
            }
        }
    }

    MKCoordinateRegion region = { coords, {0.1, 0.1} };
    [self.mapView setRegion:region animated:NO];
    [self.mapView addAnnotation: annotation];
    [self.mapView setCenterCoordinate:newLoc.coordinate animated:NO];
}

But only last location in the array and its region are displayed in the mapView when running the iPhone simulator. I'd like to simulate that user is "moving" each 1 sec, how could I do that?

Thanks!


回答1:


Looping through all the locations all at once with a sleep at each iteration won't work because the UI will be blocked until the method the loop is in finishes.

Instead, schedule the moveUser method to be called individually for each location so that the UI is not blocked throughout the sequence. The scheduling can be done using an NSTimer or possibly something simpler and more flexible such as the performSelector:withObject:afterDelay: method.

Keep an index ivar to keep track of which location to move to each time moveUser is called.

For example:

//instead of the loop, initialize and begin the first move...
slIndex = 0;  //this is an int ivar indicating which location to move to next
[self manageUserMove];  //a helper method

-(void)manageUserMove
{
    CLLocation *newLoc = [simulatedLocs objectAtIndex:slIndex];

    [self moveUser:newLoc];

    if (slIndex < (simulatedLocs.count-1))
    {
        slIndex++;
        [self performSelector:@selector(manageUserMove) withObject:nil afterDelay:1.0];
    }
}

The existing moveUser: method does not have to be changed.


Note that the user experience and code can be simplified if instead of removing and adding the annotation again every time, you add it once at the beginning and just change its coordinate property at each "move".




回答2:


You should not be using MKAnnotation, but MKPolyline. Check the documentation. Also, check the WWDC MapKit video from 2010. It has a n example of a mutable MKPolyline.




回答3:


Your problem is that the for loop with the sleep in it, is blocking the main thread until the end of the for loop. That freezes the whole user interface for that whole period, including any changes you do in moveUser.

Instead of the for loop, use an NSTimer that fires every second and does one step each time.

Or possibly, for a smoother effect, setup an animation that moves the position of the annotation along a predefined path.



来源:https://stackoverflow.com/questions/12918453/trying-to-simulate-a-route-in-mapview

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!