iOS 11 定位技术中的一些新特性

作者:tingxins,博客: https://tingxins.com

定位技术在 App 开发过程中占据非常重要的位置,尤其是在一些户外型 App,如:Keep、共享单车等。正是因为定位技术,他们才能给用户最佳体验。在 iOS 11 中,定位技术又做出了一些改进,特别是在授权访问,并且用户体验也得到了较大的提升。本文末尾也会简单提及 iOS 11 中如何针对这块进行适配。

概览

  • API 改进
  • 授权与使用指示
  • 最佳实践

API 改进

CLGeocoder API

在 iOS 11 中,CLGeocoder 开始支持 Contacts 框架了。

首先,CLGeocoder 中此方法已过期:

-(void)geocodeAddressDictionary:(NSDictionary *)addressDictionary completionHandler:(CLGeocodeCompletionHandler)completionHandler

现在 CLGeocoder 中新增了几个 API:

  • 其中新增的下面这个方法来代替了上述方法:

     - (void)geocodePostalAddress:(CNPostalAddress *)postalAddress completionHandler:(CLGeocodeCompletionHandler)completionHandler;
  • 在 iOS 11 进行地理编码时,现在支持使用区域设置了,API 如下:

    -(void)reverseGeocodeLocation:(CLLocation *)location preferredLocale:(nullable NSLocale *)locale completionHandler:(CLGeocodeCompletionHandler)completionHandler;
    
    -(void)geocodeAddressString:(NSString *)addressString inRegion:(nullable CLRegion *)region preferredLocale:(nullable NSLocale *)locale completionHandler:(CLGeocodeCompletionHandler)completionHandler;
    
    -(void)geocodePostalAddress:(CNPostalAddress *)postalAddress preferredLocale:(nullable NSLocale *)locale completionHandler:(CLGeocodeCompletionHandler)completionHandler;

我们可通过 geocodePostalAddress 相关 API 进行地理编码,可以把邮政地址(CNPostalAddress)转成地标(CLPlacemark),并且在 CLPlacemark 中还可以拿到 postalAddress (CNPostalAddress)邮政地址,需要注意的是 addressDictionary 方法已经过期。(Some Exciting Changed for you).

@property (nonatomic, readonly, copy, nullable) NSDictionary *addressDictionary;

举个例子简单展示如何通过地理编码把邮政地址转成地标:

CNMutablePostalAddress *postalAddress = [[CNMutablePostalAddress alloc] init];
postalAddress.street = @"Keyan Road No.9 Nanshan";
postalAddress.city = @"Shenzhen";
postalAddress.state = @"Guangdong";
postalAddress.postalCode = @"518000";
postalAddress.country = @"China";
postalAddress.ISOCountryCode = @"CN";

if (@available(iOS 11.0, *)) {
   [self.geocoder geocodePostalAddress:postalAddress completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
       if (!error) {
           NSLog(@"**********geocodePostalAddress************");
           CLPlacemark *placemark = placemarks.lastObject;
           NSLog(@"%@", placemark.name);
           NSLog(@"**********geocodePostalAddress************");
       }
   }];
} else {
   // Fallback on earlier versions
}

// print
**********geocodePostalAddress************
No. Nine Keyan Road
**********geocodePostalAddress************

我们再针对区域设置举个例子,注意,用户的手机语言主体是英语,但我们在针对邮政地址进行地理编码时任然可以通过设置 preferredLocale 参数来得到我们想要的不同语言的地标信息。

NSLocale *locale = [[NSLocale alloc] initWithLocaleIdentifier:@"zh_Hans_CN"];
[self.geocoder geocodePostalAddress:postalAddress preferredLocale:locale completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
  if (!error) {
      NSLog(@"**********geocodePostalAddress-preferredLocale************");
      CLPlacemark *placemark = placemarks.lastObject;
      NSLog(@"%@--%@", placemark.name, placemark.postalAddress);
      NSLog(@"**********geocodePostalAddress-preferredLocale************");
  }
}];

// print
**********geocodePostalAddress-preferredLocale************
科研路9号
**********geocodePostalAddress-preferredLocale************

通过打印信息可看出,设置了 preferredLocale 后,得到的 placemark 是中文信息。

指向与移动方向(Heading & Course)

Core Location 支持两种方式来获取方向相关的信息:Heading & Course

用过地图的导航同学都知道,地图上有一个带方向的定位小蓝点,并且能够随着手机的转动而转动,这使得用户能够辨别当前的方向,从而提高导航用户体验,这是通过 CLHeading 来实现的。但苹果认为,有时候单靠 Heading 是不靠谱的,Heading 仅代表用户面朝方向,而 Course 苹果则解释为用户实际移动的方向。因此 HeadingCourse 相结合能够带来更好的用户体验。

  • Heading(指向):即设备的指向(设备中的磁力计计算结果)。
  • Course(移动方向):即设备的移动方向(通过 GPS 计算),不考虑设备的指向。

至于使用 Heading 还是 Course 最终取决于 App 的使用,有时候我们可能是其中一种或者结合两种方式来使用。比如,我们在步行的时候,使用 Heading 可能更加合适;而在驾驶过程中,则使用 Course 更加合适,因为它能代表汽车的行驶方向。

在 iOS 11 中,Heading & Course 得到了增强,Core Location 会自动探测当前情况,使得 HeadingCourse 达成一定的'共识',并且 Course 提供的信息能使 Heading 的信息更加精准。两者的特点如下:

  • 更精准的设备指向估算
  • 全自动化

在 iOS 11 中,也为 CMDeviceMotion 新增的一个属性 heading,用于获取 CLHeading 原始值。

/*
 *  heading
 *
 *  Discussion:
 *    Returns heading angle in the range [0,360) degrees with respect to the CMAttitude reference frame. A negative value is returned
 *    for CMAttitudeReferenceFrameXArbitraryZVertical and CMAttitudeReferenceFrameXArbitraryCorrectedZVertical.
 *
 */
@property(readonly, nonatomic) double heading NS_AVAILABLE(NA, 11_0);

授权(Authorization)

此模块是今年最大的一个更新点。

授权模式(Authorization Modes)

top Created with Sketch.