我有一个从文件中解析的CLLocation
个对象数组。我想模拟用户沿着那条路走,我已经实现了这个:
for (CLLocation *loc in simulatedLocs) {
[self moveUser:loc];
sleep(1);
}
这是循环中调用的方法:
- (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];
}
但是在运行iPhone模拟器时,只有数组中的最后一个位置及其区域显示在mapView中。我想模拟用户每1秒“移动”一次,我该怎么做?
谢谢!
答案 0 :(得分:2)
在每次迭代时使用sleep
一次循环遍历所有位置将不起作用,因为在循环完成的方法之前UI将被阻止。
相反,安排为每个位置单独调用moveUser
方法,以便在整个序列中不阻止UI。调度可以使用NSTimer
完成,也可以更简单,更灵活,例如performSelector:withObject:afterDelay:
方法。
保留索引ivar以跟踪每次调用moveUser
时要移动到的位置。
例如:
//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];
}
}
不必更改现有的moveUser:
方法。
请注意,如果不是每次都删除和添加注释,而是在开头添加一次,只需在每次“移动”时更改其coordinate
属性,就可以简化用户体验和代码。
答案 1 :(得分:0)
你不应该使用MKAnnotation,而是使用MKPolyline。检查documentation。此外,请检查2010年的WWDC MapKit视频。它有一个可变的MKPolyline的例子。
答案 2 :(得分:0)
你的问题是带有sleep的for循环阻塞了主线程,直到for循环结束。这会冻结整个用户界面,包括你在moveUser中所做的任何更改。
使用每秒触发并且每次都执行一步的NSTimer,而不是for循环。
或者,为了获得更平滑的效果,可以设置一个动画,沿预定义的路径移动注释的位置。