我正在开发一个应用程序,旨在在地图上显示 iPhone 在活动期间的位置(在它们之间添加注释和画线)。
为此,我使用位置管理器获取新位置并通知 MapDisplayViewController。当与模拟器一起使用时,我得到了很好的结果,你可以在这里看到http://www.youtube.com/watch?v=ESLIYSU_Mqw但是使用 iPhone 我得到了 200 米错误的奇怪结果。
我还使用 MKMapView 来显示设备位置。通过这些设置(下一个代码块),我得到了http://grab.by/mgUU。
如果我显示用户位置我得到不同的结果,这正常吗?
- (void)setupMap {
self.mapView.delegate = self;
[self.mapView setUserTrackingMode:MKUserTrackingModeFollow animated:YES];
[self.mapView setUserInteractionEnabled:NO];
[self.mapView setShowsUserLocation:NO];
[self.mapView setZoomEnabled:NO];
[self.waitingView start];
}
下面是真机截图:
- 背景: http: //grab.by/mgN2
- 没有背景: http: //grab.by/mgNc
编辑:差异来自我在这两种情况下使用的两种不同的获取设备当前位置的方法:
- 应用程序处于活动状态时来自 mapView 的句柄
- 应用程序在后台时来自位置管理器的句柄
混合两个位置系统是个好主意吗?
我还测试了这个解决方案CLLocationManager 和准确性问题 - 有什么经验吗?但我得到了同样的结果。
谢谢 ;)
位置管理器的设置:
- (void)setup {
self.locationManager = [CLLocationManager new];
self.locationManager.delegate = self;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
self.isUpdatingLocation = NO;
}
通知:在后台添加位置时:
- (void)doUpdateWithLocation:(CLLocation *)location {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self beginBackgroundUpdateTask];
NSLog(@"%s do update in background %@", __PRETTY_FUNCTION__, location);
if (self.userLocationFound == NO && self.isUpdatingLocation == YES) {
self.startCoordinate = CLLocationCoordinate2DMake(location.coordinate.latitude, location.coordinate.longitude);
self.userLocationFound = YES;
}
else if (self.isUpdatingLocation) {
static int distance;
ABGPSPosition *position = [[ABGPSPosition alloc] init];
position.startPoint = MKMapPointForCoordinate(self.startCoordinate);
position.endPoint = MKMapPointForCoordinate(location.coordinate);
//INFO: Get the distance between this new point and the previous point.
CLLocationDistance metersApart = MKMetersBetweenMapPoints(position.startPoint, position.endPoint);
if (metersApart > MINIMUM_DELTA_METERS) {
MKMapPoint points[2] = {position.startPoint, position.endPoint};
distance += metersApart;
NSLog(@"%s - %d", __PRETTY_FUNCTION__, distance);
NSInteger count = [self.measurementArray count];
[self willChange:NSKeyValueChangeInsertion
valuesAtIndexes:[NSIndexSet indexSetWithIndex:count] forKey: @"measurementArray"];
[self.measurementArray insertObject:location atIndex:count];
[self didChange:NSKeyValueChangeInsertion
valuesAtIndexes:[NSIndexSet indexSetWithIndex:count] forKey: @"measurementArray"];
self.startCoordinate = CLLocationCoordinate2DMake(location.coordinate.latitude, location.coordinate.longitude);
}
}
[self endBackgroundUpdateTask];
});
}
MapDisplayViewController 获取新位置:
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if ([keyPath isEqualToString:keyPathMeasurementArray]) {
if ([change[NSKeyValueChangeKindKey] intValue] == NSKeyValueChangeInsertion) {
NSIndexSet *insertedIndexSet = change[NSKeyValueChangeIndexesKey];
[insertedIndexSet enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) {
CLLocation *location = self.locationManager.measurementArray[idx];
MKUserLocation *userLocation = [[MKUserLocation alloc] init];
[userLocation setCoordinate:location.coordinate];
NSLog(@"%s - didUpdateUserLocation", __PRETTY_FUNCTION__);
[self.locationBackgroundList addObject:userLocation];
NSLog(@"%s | %@", __PRETTY_FUNCTION__, self.locationBackgroundList);
}];
}
}
else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
MapDisplayViewController 为新的地图视图添加注解:
- (void)handleAddLocations {
NSLog(@"%s | %@", __PRETTY_FUNCTION__, self.locationBackgroundList);
if ([self.locationBackgroundList count] > 0) {
for (MKUserLocation *backgroundUserLocation in self.locationBackgroundList) {
{
LocAnnotation* annotation = [[LocAnnotation alloc] initWithCoordinate:backgroundUserLocation.coordinate];
NSLog(@"%s %@", __PRETTY_FUNCTION__, [backgroundUserLocation description]);
[self.mapView addAnnotation:annotation];
}
[self mapView:self.mapView didUpdateUserLocation:backgroundUserLocation];
}
NSString *message = [NSString stringWithFormat:@"%s | Annotation number: %d", __PRETTY_FUNCTION__, [self.locationBackgroundList count]];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Debug" message:message delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"OK", nil];
[alert show];
[self.locationBackgroundList removeAllObjects];
self.locationBackgroundList = [[NSMutableArray alloc] init];
}
}