美文网首页
UIApplication​Delegate 的launch​O

UIApplication​Delegate 的launch​O

作者: 夏天的风_song | 来源:发表于2017-05-05 14:44 被阅读0次

参考文档:
UIApplication​Delegate launch​Options
获取iOS的应用程序打开的方式
启动选项键
应用服务位置更新启动应用程序

launch​Options 用于访问启动选项字典中传递给应用程序的键
application: will Finish Launching With Options:
和应用程序application: did Finish Launching With Options:
应用程序委托的方法。


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];
}

要搞清楚所有的启动参数确实要费点力气。幸运的是一般的应用只需要处理其中的一两种就够了。了解所有的可能性需要从理解概念走到亲自实现的步骤上。当你了解到事情有那么多可能性的时候,下一个改变世界的想法可能就已经在脑中开始酝酿了。

相关文章

网友评论

      本文标题:UIApplication​Delegate 的launch​O

      本文链接:https://www.haomeiwen.com/subject/evurtxtx.html