AppDelegate就是iOS的垃圾场。
App的生命周期管理?URL处理?通知?CoreData?大量第三方SDK的初始化?还有那些看起来放到哪里都不合适的函数?统统都被塞到AppDelegate.m里面!
这所有之中,application:didFinishLaunchingWithOptions:是最拥挤的一个。
对于许多开发者来说,launchOptions参数如同Java main函数的String[]参数一样,被忽视了。然而,摆在眼前的事实是,launchOptions包含了许多关键性知识,涉及了app在iOS上的众多启动方式。
这个周,我们就谈谈这个UIKit里面最重要的方法,揭秘一下这个知之甚少的launchOptions参数。
每个app都从UIApplicationDelegate的 application:didFinishLaunchingWithOptions:方法开始启动(更精确点说,是 application:willFinishLaunchingWithOptions:方法,如果你把它实现了的话)。应用程序通过调用这个方法来通 知它的delegate:启动程序已经完成,差不多已经准备好运行了。
除了点击桌面上的应用图标可以启动程序外,还有其他几种场景可以使程序启动。例如,app如果注册了自定义的URL schemme,比如twitter://,就可以被open URL的方式调用开启程序。也可以通过推送通知或定位服务的方式调用开启程序。
launchOptions参数的所用就是用来判断一个app是如何被启动的。类似于userInfo字典,在 application:didFinishLaunchingWithOptions:方法中,可以通过launchOptions参数来获取指定 key的相关信息。
其中的许多key同样使用于UIApplicationDidFinishLaunchingNotification通知。详细信息可以查阅相关文档。
launchOptions包含了大量的key。根据app的启动方式,这些key大体可以被分为以下这几类:
通过URL,程序可以调用启动其他程序:
1 |
|
例如,”http://”的URL可以打开Safari,”mailto://”的URL可以打开邮件程序,”tel://”的URL可以拨打电话。
这些情形下,launchOptions里面会包含一个叫UIApplicationLaunchOptionsURLKey的Key。
UIApplicationLaunchOptionsURLKey: 标示了该应用程序是为了打开一个URL启动。这个Key对应的值是一个NSURL对象,表示要打开的URL。
app被URL启动的时候,还可以附带一些系统信息。当app是被UIDocumentInteractionController或AirDrop启动的时候,launchOptions里面还会附带下面这些key:
- UIApplicationLaunchOptionsSourceApplicationKey: 标示了要求启动你的程序的那个app。对应的值是一个NSString,表示那个app的bundle ID。
- UIApplicationLaunchOptionsAnnotationKey: 标示了要求打开URL的那个app提供的自定义数据。对应的值是一个property-list类型的对象, 包含自定义的数据。
1 2 3 4 5 6 7 |
|
这里的通知不是指NSNotification,而是指推送通知和本地通知。
自从iOS3引入推送通知以后,推送通知就成了移动平台最典型的功能之一。
要注册推送通知,在application:didFinishLaunchingWithOptions:里面调用registerForRemoteNotificationTypes:方法即可:
1 2 3 4 |
|
注册成功后,会收到application:didRegisterForRemoteNotificationsWithDeviceToken:这个回调。然后,就可以接收推送通知了。
接收到推送通知后,如果app当前处于前台运行状态,appDelgate的 application:didReceiveRemoteNotification:方法会被调用。然而,当app是因为用户滑动通知中心的推送消息而 启动时,application:didFinishLaunchingWithOptions:方法会被调用。这个时候,launchOption里面 会包含名为UIApplicationLaunchOptionsRemoteNotificationKey的key:
UIApplicationLaunchOptionsRemoteNotificationKey: 表明app有一个推送通知等待处理。这个key对应的值是一个包含了推送通知负载信息的NSDictionary,包括以下这些信息:
alert:alert可以是一个字符串,表示提示信息;也可以是一个包含两个key(body和show-view)的字典。
badge:badge是一个数字,用于标示可从提供者下载的数据数量。这数字会被显示在app的图标上。如果推送通知中不包含badge这个字段,则app图标上标记的数字会被移除掉。
sound:指定app bundle里面用作提示音的声音文件的名字。如果为”default”,则会播放系统默认的提示音。
这样看来,就有两个地方要写处理推送通知的代码。因此,一个通常的做法是在application:didFinishLaunchingWithOptions:里面手动调用application:didReceiveRemoteNotification::
1 2 3 4 5 6 7 8 |
|
本地通知从iOS4引入。令人惊奇的是,时至今日,仍然有很多人没有把它搞明白。
app可以定时触发一些UILocalNotification通知。通知触发时候,如果app正处于前台运行状态,appDelegate的 application:didReceiveLocalNotification:方法会被调用。如果app处于非活动状态,通知就会被发布到通知中 心。
与推送通知不同,UIApplication的delegate方法提供了一个统一的处理本地通知的地方。如果一个app是被本地通知启动的,会先 调用application:didReceiveLocalNotification:方法,然后才会调用 application:didFinishLaunchingWithOptions:(因此,就不需要在 application:didFinishLaunchingWithOptions:里面手动调用 application:didReceiveLocalNotification了)。
本地通知在launchOptions里面的key为UIApplicationLaunchOptionsLocalNotificationKey,对应的值为UILocalNotification对象(原文此处有误,本地通知和推送通知的结构不是相同的)。
UIApplicationLaunchOptionsLocalNotificationKey: 如果这个key出现在launchOptions里面,则说明app有一个本地通知等待处理。对应的值是一个UILocalNotification对 象,表示触发的本地通知。
为了直观的展示,当app处于前台活动状态时应该如何显示一个本地通知的提示框。请看下面这个例子:
1 2 3 4 5 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
|
想创造一个基于地理位置信息的本地社交图片签到软件?好吧,你已经晚了4年了。
但是不用怕!使用iOS的位置监测,你的app可以被定位事件启动:
UIApplicationLaunchOptionsLocationKey: 表明app是为了响应定位事件才启动的。这个key对应的值是一个包含一个BOOL值的NSNumber对象。监测到这个key后,你应当创建 CLLocationManager对象并再次启动定位服务。定位数据只会被投递给location manager的delegate,不会用这个key投递。
下面这个例子,展示了当app收到一个显著的位置变化(significant location)事件而启动时的处理过程:
1 2 3 4 5 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
所有Newsstand开发者,欢呼吧。
好吧好吧。
Newsstand可以在有新的下载资源时被启动。
你可以像这样注册:
1 2 |
|
接下来就是launchOptions里面的关键部分:
UIApplicationLaunchOptionsNewsstandDownloadsKey: 表明有新的Newsstand资源可供你的app下载。这个key对应的值是一组字符串标示符,它们标示了可供下载的资源对应的 NKAssetDownload对象。虽然,这些标示符可以用作重复核对的用途,但是,你应当通过NKLibrary对象(表示Newsstand app的资源库)的downloadingAssets属性来明确的获取NKAssetDownload对象数组(它们表示了正在下载或者有错误的资 源)。
除此之外,就没有什么需要多说的了。
iOS7引入了一个新功能,允许app被蓝牙外围设备重新启动。
如果app用特定的标示符实例化了一个CBCentralManager或一个CBPeripheralManager对象,并且连接了其他蓝牙外围设备,app就可以被来自蓝牙系统的中央操作(certain actions)重新启动。取决于接到通知的是中央设备管理器还是外围设备管理器,launchOptions里面会包含下面这两个key中的其中一个:
UIApplicationLaunchOptionsBluetoothCentralsKey: 表明app先前有一个或多个CBCentralManager对象,现在app被蓝牙系统重新启动以继续处理这些对象的相关操作。这个key对应的值是一 个包含了一个或多个NSString对象的数组。 每个字符串代表了一个中央设备管理器对象的复位标示符。
UIApplicationLaunchOptionsBluetoothPeripheralsKey: 表明app先前有一个或多个CBPeripheralManager对象,现在app被蓝牙系统重新启动以继续处理这些对象的相关操作。这个key对应的 值是一个包含了一个或多个NSString对象的数组。每个字符串代表了一个外围设备管理器对象的复位标示符。
1 2 3 4 5 |
|
1 2 3 4 5 6 7 8 |
|
要记住这么多app启动的方法和手段可能会让人感到筋疲力尽。幸运的是,任何一个app可能只需要处理其中的一两种情况就可以了。
知道什么是可能的,通常是能让一个app从概念演变成实现的必要条件。因此记住所有这些选项吧,以备你脑海中浮现出来的下一个伟大想法。
原网页:http://codingobjc.com/blog/2014/01/08/uiapplicationdelegate-launchoptions/