参考文档:
UIApplicationDelegate launchOptions
获取iOS的应用程序打开的方式
启动选项键
应用服务位置更新启动应用程序
launchOptions 用于访问启动选项字典中传递给应用程序的键
application: will Finish Launching With Options:
和应用程序application: did Finish Launching With Options:
应用程序委托的方法。
-
UIApplication Launch Options URLKey
此键的存在表示该应用程序已启动,以便打开一个URL。 该键的值是包含要打开的URL的NSURL
对象。 -
UIApplication Launch Options Source Application Key
此键的存在标识了请求启动您的应用程序的应用程序。 该键的值是一个NSString
对象,表示发出请求的应用程序的包ID。 -
UIApplication Launch Options Remote Notification Key
该键的存在表示可以使应用程序进行远程通知。 该键的值是包含NSDictionary
通知的有效载荷的NSDictionary。 请参阅应用程序的application: did Receive Remote Notification:
有关处理远程通知的更多信息。 -
UIApplication Launch Options Annotation Key
此键的存在表示自定义数据是由请求打开URL的应用程序提供的。 该键的值是包含自定义数据的属性列表对象。 相同的对象也被传递给应用程序的application: open URL: source Application: annotation:
方法。 此属性列表对象的内容特定于发出请求的应用程序。 -
UIApplication Launch Options Location Key
该键的存在表示应用程序是响应于传入位置事件而启动的。该键的值是包含NSNumber
布尔值的对象。您应该使用此键的存在作为信号来创建对象并重新启动位置服务。位置数据仅传递给位置管理器委托,而不使用该键。CLLocationManager
-
UIApplication Launch Options Newsstand Downloads Key
此键的存在表明新下载的报亭资产可用于您的应用程序。 该键的值是一组字符串标识符,用于标识与资产相对应的NKAsset Download对象。 虽然您可以使用标识符进行交叉检查,但您应该通过代表报亭应用程序库的NKLibrary对象的downloading Assets
属性来获取NKAsset Download对象的最终数组(表示正在进行或错误的资产NKAsset Download
)。 -
UIApplication Launch Options Bluetooth Centrals Key
此键的存在表明应用程序以前具有一个或多个CBCentral Manager
对象,并由蓝牙系统重新启动,以继续与这些对象相关联的操作。 该键的值是包含一个或多个NSString
对象的NSArray
对象。 -
UIApplication Launch Options Bluetooth Peripherals Key
该键的存在表明应用程序以前具有一个或多个CBPeripheral Manager
对象,并由蓝牙系统重新启动,以继续与这些对象相关联的操作。 该键的值是包含一个或多个NSString
对象的NSArray
对象。 -
UIApplication Launch Options Shortcut Item Key
包含UIApplication Shortcut Item
对象,表示用户选择启动或激活您的应用程序的主屏幕快速操作。 -
UIApplication Launch Options User Activity Dictionary Key
此键的存在表示该应用程序已启动,以便继续进行用户活动。该键的值是包含键UIApplication Launch Options User Activity Type Key
的NSDictionary
对象,其值是标识活动类型的NSString
对象。 -
UIApplication Launch Options User Activity Type Key
该键用于子字典,它是UIApplication Launch Options Shortcut Item Key
的值。 该键的值是标识活动类型的NSString
对象。
AppDelegate 是 iOS 各种功能的集散中心。
应用生命周期管理?URL 路由?通知?Core Data 咒语?各种三方 SDK 的初始化?一些似乎放在哪里都不合适的零散功能?统统丢进 AppDelegate.m 里吧!
在 AppDelegate 所有这些拥挤的、超出负载的方法中,-application:didFinishLaunchingWithOptions: 是最臃肿的一个了。
对于很多开发者来说 launchOptions 参数就是类似于 Java 的 main 函数中 String[] args 的作用 —— 在构建应用时候一般是被忽略的。在其平淡的外表下,launchOptions 其实隐藏着 iOS 应用启动时携带的大量核心信息。
每个应用都使用 UIApplicationDelegate -application:didFinishLaunchingWithOptions:(更精确地说以后或许也包含 -application:willFinishLaunchingWithOptions:) 启动。应用调用这个方法来告诉 delegate 进程已经启动完毕,已经准备好运行了。
在 Springboard 中点击图标应用就开始启动了,但也有其他一些启动的方法。比如说注册了自定义 URL scheme 的应用可以以类似于twitter://
的方式从一个 URL 启动。应用可以通过推送通知或地理位置变更启动。
查明应用为什么以及是如何启动的,就是 launchOptions 参数的职责所在。就像 userInfo 字典一样,在-application:didFinishLaunchingWithOptions:
的 launchOptions 中也包含很多特别命名的键。
这些键中的许多在应用启动时发出的 UIApplicationDidFinishLaunchingNotification 的通知中也可用,详细内容请查阅文档。
launchOptions 包含的键太多了,按照应用启动原因分组理解起来更容易一点:
一、从URL打开
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"app://..."]];
例如:http:// 开头的 URL 会在 Safari 中打开,mailto:// 开头的 URL 会在邮件中打开,tel:// 开头的 URL 会在电话中打开。
这些情况下 UIApplicationLaunchOptionsURLKey 键就会很常用了。
- UIApplicationLaunchOptionsSourceApplicationKey为调用openurl打开的源程序的bundle id。
- UIApplicationLaunchOptionsURLKey 为openurl所传的参数,如果app有多个url schema时可以在这里做判断。
//- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
launchOptions {
UIApplicationLaunchOptionsSourceApplicationKey = "com.Juny-RouterDemo";
UIApplicationLaunchOptionsURLKey = "APPSkip://RedVC";
}
//- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options
options {
UIApplicationOpenURLOptionsOpenInPlaceKey = 0;
UIApplicationOpenURLOptionsSourceApplicationKey = "com.Juny-RouterDemo";
}
应用也可以通过 URL 和附加系统信息打开。当应用从 AirDrop 的 UIDocumentInteractionController 中打开时,launchOptions 会包含下列这键:
- UIApplicationLaunchOptionsSourceApplicationKey:请求打开应用的应用 id。对应的值是请求打开应用的 bundle ID 的 NSString 对象
- UIApplicationLaunchOptionsAnnotationKey:标示通过 URL 打开应用时携带了自定义数据。对应的值是包含自定义数据的属性列表对象
NSURL *fileURL = [[NSBundle mainBundle] URLForResource:@"Document" withExtension:@"pdf"];
if (fileURL) {
UIDocumentInteractionController *documentInteractionController = [UIDocumentInteractionController interactionControllerWithURL:fileURL];
documentInteractionController.annotation = @{@"foo": @"bar"};
[documentInteractionController setDelegate:self];
[documentInteractionController presentPreviewAnimated:YES];
}
二、响应通知
不要和 NSNotification
混淆了,应用可以通过本地(local)或远程(remote)通知打开。
应用可以制定计划在未来某个时间点触发 UILocalNotification。如果应用处于打开状态,那么将回调-application:didReceiveLocalNotification:
方法。如果应用处于非活跃状态,通知将会被发送到通知中心。
不像推送通知,UIApplication 的 delegate 提供了统一控制本地通知的方法。如果应用是通过本地通知启动的,-application:didReceiveLocalNotification:
将会在-application:didFinishLaunchingWithOptions:
之后被自动调用(意思就是不需要像推送通知一样在 -application:didFinishLaunchingWithOptions:` 中手动调用了)。
本地通知会在启动参数中携带和推送通知有类似结构的 UIApplicationLaunchOptionsLocalNotificationKey:
- UIApplicationLaunchOptionsLocalNotificationKey: 标示本地通知目前处于可用状态。对应的值是包含通知内容的 NSDictionary。
//远程推送UIApplicationLaunchOptionsRemoteNotificationKey 直接是一个推送的JSON内容。
launchOptions {
UIApplicationLaunchOptionsRemoteNotificationKey = {
aps = {
alert = test;
badge = 1;
sound = default;
};
};
}
//通过本地推送(localnotification)打开.UIApplicationLaunchOptionsLocationNotificationKey为本地推送的内容。
launchOptions {
UIApplicationLaunchOptionsLocationNotificationKey = "<UIConcreteLocalNotification: 0x1e5c8b60>{fire date = 2017\U5e749\U67089\U65e5\U661f\U671f\U4e00 \U4e2d\U56fd\U6807\U51c6\U65f6\U95f411\U65f613\U520655\U79d2, time zone = Asia/Shanghai (GMT+0800) offset 28800, repeat interval = 0, repeat count = UILocalNotificationInfiniteRepeatCount, next fire date = (null), user info = {\n}}";
}
三、地理位置事件
iOS的位置监控,可以让我们的应用通过地理位置触发事件的启动
UIApplicationLaunchOptionsLocationKey:该键的存在表示应用程序是响应于传入位置事件而启动的。该键的值是包含NSNumber 布尔值的对象。您应该使用此键的存在作为信号来创建对象并重新启动位置服务。位置数据仅传递给位置管理器委托,而不使用该键。CLLocationManager。
我们需要一直跟踪用户位置(但又不想耗尽电池)。我们能在程序被杀死后获取位置更新的唯一方法是使用startMonitoringSignificantLocationChanges
**startMonitoringSignificantLocationChanges**
如果您启动此服务,并且应用程序随后终止,则如果新事件到达,系统将自动重新启动应用程序到后台。在这种情况下,将选项字典传递给应用程序:didFinishLaunchingWithOptions:应用程序委托方法包含UIApplicationLaunchOptionsLocationKey键,表示您的应用程序是由于位置事件而启动的。重新启动后,您仍然必须配置位置管理器对象并调用此方法来继续接收位置事件。当您重新启动位置服务时,当前事件将立即发送给您的代表。此外,即使在启动位置服务之前,您的位置管理器对象的位置属性也会填充最新的位置对象。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
if (![CLLocationManager locationServicesEnabled]) {
[[[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Location Services Disabled", nil)
message:NSLocalizedString(@"You currently have all location services for this device disabled. If you proceed, you will be asked to confirm whether location services should be reenabled.", nil)
delegate:nil
cancelButtonTitle:NSLocalizedString(@"OK", nil)
otherButtonTitles:nil] show];
} else {
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
//
[self.locationManager startMonitoringSignificantLocationChanges];
}
if (launchOptions[UIApplicationLaunchOptionsLocationKey]) {
[self.locationManager startUpdatingLocation];
}
return YES;
}
//////位置改变的代理
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation {
if ( abs([newLocation.timestamp timeIntervalSinceDate: [NSDate date]]) < 30) {
self.lastLocation = newLocation;
[self updateLocation]; //sending location to server
}
三、报刊杂志(Newsstand)
当有新的可用下载时,报刊杂志应用可以启动。
这样注册即可:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
[application registerForRemoteNotifications];
return YES;
}
然后在启动项里面找这个键:
UIApplicationLaunchOptionsNewsstandDownloadsKey:标示应用有新的可用杂志资源下载。对应的值是包含 NKAssetDownload id 的字符串数组。虽然你可以通过这些 id 进行检查,但还是应该通过 NKLibrary 对象的 downloadingAssets 属性来持有这些 NKAssetDownload 对象(可用用于展示下载进度或错误)以便显示在报刊杂志书架中。
四、蓝牙
iOS7开始支持外围蓝牙设备重新唤醒应用。
应用启动后通过特定的id实例化一个CBCentralManager或CBPeripheralManager用于连接蓝牙设备,之后 应用就可以通过蓝牙系统的相关动作来重新唤醒了。取决于发出通知的是一个中心设备还是外围设备,launchOptions会传入一下两个键中的一个:
UIApplicationLaunchOptionsBluetoothCentralsKey:标示应用之前曾有过一个或多个CBCentralManager对象并被蓝牙系统的相关动作唤醒过。对应的值是包含NSString对象的数组。数组中每一个字符串表示一个中心设备的恢复连接id。
标示应用之前曾有过一个或多个 CBPeripheralManager 对象并被蓝牙系统的相关动作唤醒过。对应的值是包含 NSString 对象的数组。数组中每一个字符串表示一个外围设备的恢复连接 id。
// .h
@import CoreBluetooth;
@interface AppDelegate () <CBCentralManagerDelegate>
@property (readwrite, nonatomic, strong) CBCentralManager *centralManager;
@end
// .m
self.centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil options:@{CBCentralManagerOptionRestoreIdentifierKey:(launchOptions[UIApplicationLaunchOptionsBluetoothCentralsKey] ?: [[NSUUID UUID] UUIDString])}];
if (self.centralManager.state == CBCentralManagerStatePoweredOn) {
static NSString * const UID = @"7C13BAA0-A5D4-4624-9397-15BF67161B1C"; // generated with `$ uuidgen`
NSArray *services = @[[CBUUID UUIDWithString:UID]];
NSDictionary *scanOptions = @{CBCentralManagerScanOptionAllowDuplicatesKey:@YES};
[self.centralManager scanForPeripheralsWithServices:services options:scanOptions];
}
要搞清楚所有的启动参数确实要费点力气。幸运的是一般的应用只需要处理其中的一两种就够了。了解所有的可能性需要从理解概念走到亲自实现的步骤上。当你了解到事情有那么多可能性的时候,下一个改变世界的想法可能就已经在脑中开始酝酿了。
网友评论