Today extensions,或者说“Widgets”是iOS 8中的一个新特性,它让开发者能够将应用的核心功能放到通知中心里。如果一个应用依赖地理位置,那么Widget也将需要地理位置。
在Widget里获取用户的地理位置是一个常见的用例,比如应用可能需要检测当地的天气,或者显示一个通知来介绍附近有趣的地方。幸运的是在Widget里获取地理位置和和app里一样简单。
在Widget中获取地理位置方法的简化步骤如下:
在应用里
添加一个带有描述字符串的NSLocationWhenInUseUsageDescription的键到应用的Info.plist里。
在Widget里
· 导入CoreLocation框架
· 创建一个地理位置管理器(CLLocationManager)
· 请求授权并且启动地理位置管理器
· 响应委托方法
在Info.plist里添加使用用户地理的原因,当应用程序请求使用用户地理位置时,需要以文本的形式向用户展示。
请求许可
如果主应用(container app)需要使用地理位置,你可以在应用中请求用户需求,Widget将自动请求相同的许可。如果用户在打开主应用之前打开了应用的Widget,许可的请求将在Widget中显示,随后主应用会自动进行相同的许可请求,无需提示。
Widget无需每时每刻都获取地理位置,使用WhenInUse就足够了。Widget只能在前台运行,不能因后台任务而唤醒。如果你的应用需要Always授权,你需要在Widget请求同样的授权类型。
缓存地理位置
如果你需要你的Widget快速修正位置,你可以为主应用程序请求后台定位,使用有效的位置更改服务,并在共享容器中分享地理位置,这样Widget就能在第一次唤起时迅速获得地理位置。
代码实现
这里是一个Today Extension中请求WhenInUse授权的地理位置的示例。它给当前位置的经纬度设置了一个文字标签。如果出现错误,标签将显示错误信息以代替NSLog()调试。
#import "TodayViewController.h"
#import "CoreLocation";
@interface TodayViewController ()
@property (strong, nonatomic) CLLocationManager *locationManager;
@property (weak, nonatomic) IBOutlet UILabel *locationLabel;
@end
@implementation TodayViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
// iOS 8 and higher
if ([self.locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)]) {
// TODO: Remember to add the NSLocationWhenInUseUsageDescription plist key
[self.locationManager requestWhenInUseAuthorization];
}
[self.locationManager startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
CLLocation *location = [locations lastObject];
// Output the time the location update was received
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
dateFormatter.dateStyle = NSDateFormatterNoStyle;
dateFormatter.timeStyle = NSDateFormatterMediumStyle;
NSString *timeString = [dateFormatter stringFromDate:[NSDate date]];
// Create a string from the CLLocation
NSString *latLonString = [self stringFromCoordinate:location.coordinate];
// Set the main label of the Widget to the date and coordinate
self.locationLabel.text = [NSString stringWithFormat:@"%@ %@", timeString, latLonString];
}
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
self.locationLabel.text = error.localizedDescription;
}
- (NSString *)stringFromCoordinate:(CLLocationCoordinate2D)coordinate
{
return [NSString stringWithFormat:@"%f %f", coordinate.latitude, coordinate.longitude];
}
- (void)widgetPerformUpdateWithCompletionHandler:(void (^)(NCUpdateResult))completionHandler
{
completionHandler(NCUpdateResultNewData);
}
@end