iPhone 上的 CLLocationManager 也有很多问题。
从不同的应用程序中,经过反复试验,这是我发现的;
1) 对locationManager使用单例类,只有一个实例,参照以下示例:
Apple 的 LocateMe 示例
推特罗:http://tweetero.googlecode.com/svn/trunk
我认为您只能运行一个位置管理器,iPhone 中只有一个 GPS 芯片,因此如果您启动多个位置管理器对象,它们会发生冲突,并且您会从 GPS 位置管理器中收到错误,说明它可以不更新。
2) 更新locationManager.desiredAccuracy 和
locationManager.distanceFilter
在 FlipsideViewController 中遵循 Apple 代码中的示例:
[MyCLController sharedInstance].locationManager.desiredAccuracy = accuracyToSet;
[MyCLController sharedInstance].locationManager.distanceFilter = filterToSet;
这种方法有效,不会导致错误。如果您更新所需的Accuracy 或
主委托循环中的 distanceFilter:
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
Core Location 可能会抱怨它无法更新值,并给您错误。
此外,仅使用 Apple 提供的 desiredAccuracy 的常量,不要使用其他常量,
因此;
kCLLocationAccuracyBest,kCLLocationAccuracyNearestTenMeters,
kCLLocationAccuracyHundredMeters, kCLLocationAccuracyKilometer,
kCLLocationAccuracyThreeKilometers
使用其他值可能会给您带来来自 locationManager 的错误。
对于distanceFilter,您可以使用任何值,但请注意人们已经表示它有问题,
默认的主要值是:-1 = 最佳,我用过 10.0,看起来还可以。
3) 要强制更新,请像在 Tweetero 中一样调用 startUpdates 方法,这会强制
locationManager 来做这件事,它应该尝试给你一个新的价值。
4) 核心位置委托例程很难获得准确的更新。
当您的应用程序首次初始化时,您的精度可能会相差 1000 米或更多,因此
一次尝试是行不通的。初始化后的三次尝试通常会让你
到 47 米左右,这很好。请记住,每次连续的尝试都在进行
花费越来越长的时间来提高您的准确性,因此它很快就会变得昂贵。
这是你需要做的:
仅当它是最近的 AND 时才取一个新值
如果新位置的准确度略高,则采用新位置或
如果新位置的精度
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
locationDenied = NO;
if(![[NSUserDefaults standardUserDefaults] boolForKey:@"UseLocations"])
{
[self stopAllUpdates];
return;
}
NSDate* eventDate = newLocation.timestamp;
NSTimeInterval howRecent = abs([eventDate timeIntervalSinceNow]);
attempts++;
if((newLocation.coordinate.latitude != oldLocation.coordinate.latitude) && (newLocation.coordinate.longitude != oldLocation.coordinate.longitude))
locationChanged = YES;
else
locationChanged = NO;
#ifdef __i386__
//Do this for the simulator since location always returns Cupertino
if (howRecent < 5.0)
#else
// Here's the theory of operation
// If the value is recent AND
// If the new location has slightly better accuracy take the new location OR
// If the new location has an accuracy < 50 meters take the new location OR
// If the attempts is maxed (3 -5) AND the accuracy < 150 AND the location has changed, then this must be a new location and the device moved
// so take this new value even though it's accuracy might be worse
if ((howRecent < 5.0) && ( (newLocation.horizontalAccuracy < (oldLocation.horizontalAccuracy - 10.0)) || (newLocation.horizontalAccuracy < 50.0)
|| ((attempts >= attempt) && (newLocation.horizontalAccuracy <= 150.0) && locationChanged)))
#endif
{
attempts = 0;
latitude = newLocation.coordinate.latitude;
longitude = newLocation.coordinate.longitude;
[currentLocation release];
currentLocation = [newLocation retain];
goodLocation = YES;
[[NSNotificationCenter defaultCenter] postNotificationName: @"UpdateLocationNotification" object: nil];
if (oldLocation != nil) {
distanceMoved = [newLocation getDistanceFrom:oldLocation];
currentSpeed = newLocation.speed;
distanceTimeDelta = [newLocation.timestamp timeIntervalSinceDate:oldLocation.timestamp];
}
}
// Send the update to our delegate
[self.delegate newLocationUpdate:currentLocation];
}
如果您有 iPhone 3GS,获取标题更新要容易得多,下面是与上述相同模块中的代码:
//This is the Heading or Compass values
- (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading {
if (newHeading.headingAccuracy > 0)
{
[newHeading retain];
// headingType = YES for True North or NO for Magnetic North
if(headingType) {
currentHeading = newHeading.trueHeading;
} else {
currentHeading = newHeading.magneticHeading;
}
goodHeading = YES;
[[NSNotificationCenter defaultCenter] postNotificationName: @"UpdateHeadingNotification" object: nil];
}
}
希望这对人们有所帮助!