UIApplication​Delegate launch​Options

2024-02-18 15:08

本文主要是介绍UIApplication​Delegate launch​Options,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!


Mattt Thompson撰写、 Croath Liu翻译

AppDelegate 是 iOS 各种功能的集散中心。

应用生命周期管理?URL 路由?通知?Core Data 咒语?各种三方 SDK 的初始化?一些似乎放在哪里都不合适的零散功能?统统丢进 AppDelegate.m 里吧!

在 AppDelegate 所有这些拥挤的、超出负载的方法中,-application:didFinishLaunchingWithOptions: 是最臃肿的一个了。

对于很多开发者来说 launchOptions 参数就是类似于 Java 的 main 函数中 String[] args 的作用 —— 在构建应用时候一般是被忽略的。在其平淡的外表下,launchOptions 其实隐藏着 iOS 应用启动时携带的大量核心信息。

NSHipster 本周披露的知识点是关于我们平时关心最少的、但又是 UIKit 中最重要的东西:launchOptions


每个应用都使用 UIApplicationDelegate -application:didFinishLaunchingWithOptions:(更精确地说以后或许也包含 -application:willFinishLaunchingWithOptions:) 启动。应用调用这个方法来告诉 delegate 进程已经启动完毕,已经准备好运行了。

在 Springboard 中点击图标应用就开始启动了,但也有其他一些启动的方法。比如说注册了自定义 URL scheme 的应用可以以类似于 twitter:// 的方式从一个 URL 启动。应用可以通过推送通知或地理位置变更启动。

查明应用为什么以及是如何启动的,就是 launchOptions 参数的职责所在。就像 userInfo 字典一样,在 -application:didFinishLaunchingWithOptions: 的 launchOptions 中也包含很多特别命名的键。

这些键中的许多在应用启动时发出的 UIApplicationDidFinishLaunchingNotification的通知中也可用,详细内容请查阅文档。

launchOptions 包含的键太多了,按照应用启动原因分组理解起来更容易一点:

从 URL 打开

其他应用通过传递 URL 可以打开一个应用:

Objective-C
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"app://..."]];

例如:http:// 开头的 URL 会在 Safari 中打开,mailto:// 开头的 URL 会在邮件中打开,tel:// 开头的 URL 会在电话中打开。

这些情况下 UIApplicationLaunchOptionsURLKey 键就会很常用了。

  • UIApplicationLaunchOptionsURLKey: 标示应用是通过 URL 打开的。其对应的值代表应用被打开时使用的 NSURL 对象。

应用也可以通过 URL 和附加系统信息打开。当应用从 AirDrop 的 UIDocumentInteractionController中打开时,launchOptions 会包含下列这键:

  • UIApplicationLaunchOptionsSourceApplicationKey:请求打开应用的应用 id。对应的值是请求打开应用的 bundle ID 的 NSString 对象
  • UIApplicationLaunchOptionsAnnotationKey:标示通过 URL 打开应用时携带了自定义数据。对应的值是包含自定义数据的属性列表对象
Objective-C
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)通知打开。

推送通知

自 iOS 3 开始引入的 remote(或者叫 push)notification 是在移动平台上的重要特性。

在 application:didFinishLaunchingWithOptions: 中调用 registerForRemoteNotificationTypes: 来注册推送通知。

Objective-C
[application registerForRemoteNotificationTypes:UIRemoteNotificationTypeBadge |UIRemoteNotificationTypeSound |UIRemoteNotificationTypeAlert];

如果调用成功则会回调 -application:didRegisterForRemoteNotificationsWithDeviceToken:,之后该设备就能随时收到推送通知了。

如果应用在打开时收到了推送通知,delegate 会调用 application:didReceiveRemoteNotification:。但是如果是通过在通知中心中滑动通知打开的应用,则会调用application:didFinishLaunchingWithOptions: 并携带UIApplicationLaunchOptionsRemoteNotificationKey 启动参数:

  • UIApplicationLaunchOptionsRemoteNotificationKey:标示推送通知目前处于可用状态。对应的值是包含通知内容的 NSDictionary。 > -alert:一个字符串或包含两个键 body 和 show-view 的字典。 > -badge:标示从通知发出者那应该获取数据的数量。这个数字会显示在应用图标上。没有 badge 信息则表示应该从图片上移除数字显示。 > -sound:通知接收时播放音频的文件名。如果值为 "default" 那么则播放默认音频。

因为通知可以通过两种方式控制,通常的做法是在 application:didFinishLaunchingWithOptions: 中手动调用 application:didReceiveRemoteNotification:

Objective-C
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{// ...if (launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey]) {[self application:application didReceiveRemoteNotification:launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey]];}
}

本地通知

本地通知 是在 iOS 4 中加入的功能,这个功能至今都被误解了。

应用可以制定计划在未来某个时间点触发 UILocalNotification。如果应用处于打开状态,那么将回调-application:didReceiveLocalNotification: 方法。如果应用处于非活跃状态,通知将会被发送到通知中心。

不像推送通知,UIApplication 的 delegate 提供了统一控制本地通知的方法。如果应用是通过本地通知启动的,-application:didReceiveLocalNotification: 将会在 -application:didFinishLaunchingWithOptions: 之后被自动调用(意思就是不需要像推送通知一样在-application:didFinishLaunchingWithOptions: 中手动调用了)。

本地通知会在启动参数中携带和推送通知有类似结构的UIApplicationLaunchOptionsLocalNotificationKey

  • UIApplicationLaunchOptionsLocalNotificationKey: 标示本地通知目前处于可用状态。对应的值是包含通知内容的 NSDictionary

如果应用在运行中收到本地通知需要显示提示框、其他情况不显示提示框,可以手动从UILocalNotification 获取相关信息进行操作:

Objective-C
// .h
@import AVFoundation;@interface AppDelegate ()
@property (readwrite, nonatomic, assign) SystemSoundID localNotificationSound;
@end// .m
- (void)application:(UIApplication *)application
didReceiveLocalNotification:(UILocalNotification *)notification
{if (application.applicationState == UIApplicationStateActive) {UIAlertView *alertView =[[UIAlertView alloc] initWithTitle:notification.alertActionmessage:notification.alertBodydelegate:nilcancelButtonTitle:NSLocalizedString(@"OK", nil)otherButtonTitles:nil];if (!self.localNotificationSound) {NSURL *soundURL = [[NSBundle mainBundle] URLForResource:@"Sosumi"withExtension:@"wav"];AudioServicesCreateSystemSoundID((__bridge CFURLRef)soundURL, &_localNotificationSound);}AudioServicesPlaySystemSound(self.localNotificationSound);[alertView show];}
}- (void)applicationWillTerminate:(UIApplication *)application {if (self.localNotificationSound) {AudioServicesDisposeSystemSoundID(self.localNotificationSound);}
}

地理位置事件

听说你在开发一个 LBS 签到照片的应用?哈哈,看起来你的动作好像落后时代四年多了。

但不要害怕!有了 iOS 的位置监控,你的应用可以通过地理位置触发的事件启动了:

  • UIApplicationLaunchOptionsLocationKey:标示应用是响应地理位置事件启动的。对应的值是包含 Boolean 值的 NSNumber 对象。可以把这个键作为信号来创建 CLLocationManager 对象并开始进行定位。位置数据会传给 location manager 的 delegate(并不需要这个键)。

以下是检测位置变化来判断启动行为的例子:

Objective-C
// .h
@import CoreLocation;@interface AppDelegate () <CLLocationManagerDelegate>
@property (readwrite, nonatomic, strong) CLLocationManager *locationManager;
@end// .m
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{// ...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:nilcancelButtonTitle: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];}
}

报刊杂志(Newsstand)

所有的报刊杂志开发者都会为此欢呼的!

欢呼声.aiff

够了...

有新的可用下载时,报刊杂志应用可以启动。

这样注册即可:

Objective-C
[application registerForRemoteNotificationTypes:UIRemoteNotificationTypeNewsstandContentAvailability];

然后在启动参数中找到这个键:

  • UIApplicationLaunchOptionsNewsstandDownloadsKey:标示应用有新的可用杂志资源下载。对应的值是包含 NKAssetDownload id 的字符串数组。虽然你可以通过这些 id 进行检查,但还是应该通过 NKLibrary 对象的 downloadingAssets 属性来持有这些 NKAssetDownload 对象(可用用于展示下载进度或错误)以便显示在报刊杂志书架中。

详细情况不再赘述。

蓝牙

iOS 7 开始支持外围蓝牙设备重新唤醒应用。

应用启动后通过特定的 id 实例化一个 CBCentralManager 或 CBPeripheralManager 用于连接蓝牙设备,之后应用就可以通过蓝牙系统的相关动作来被重新唤醒了。取决于发出通知的是一个中心设备还是外围设备,launchOptions 会传入以下两个键中的一个:

  • UIApplicationLaunchOptionsBluetoothCentralsKey:标示应用之前曾有过一个或多个 CBCentralManager 对象并被蓝牙系统的相关动作唤醒过。对应的值是包含 NSString 对象的数组。数组中每一个字符串表示一个中心设备的恢复连接 id。
  • UIApplicationLaunchOptionsBluetoothPeripheralsKey:标示应用之前曾有过一个或多个 CBPeripheralManager 对象并被蓝牙系统的相关动作唤醒过。对应的值是包含 NSString 对象的数组。数组中每一个字符串表示一个外围设备的恢复连接 id。
Objective-C
// .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];
}

要搞清楚所有的启动参数确实要费点力气。幸运的是一般的应用只需要处理其中的一两种就够了。

了解所有的可能性需要从理解概念走到亲自实现的步骤上。当你了解到事情有这么多可能性的时候,下一个改变世界的想法可能就已经在脑中开始酝酿了。

作者 Mattt Thompson
Mattt Thompson

Mattt Thompson (@mattt) is the creator & maintainer of AFNetworking and other popular open-source projects, includingPostgres.app, ASCIIwwdc and Nomad.


这篇关于UIApplication​Delegate launch​Options的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/721546

相关文章

jQuery Mobile 的.bind()、.live()和.delegate()之间区别

资料一: live方法是bind方法的变种,其基本功能就同bind方法的功能是一样的,都是为一个元素绑定某个事件,但是bind方法只能给当前存在的元素绑定事件,对于事后采用JS等方式新生成的元素无效,而live方法则正好弥补了bind方法的这个缺陷,它可以对后生成的元素也可以绑定相应的事件。      live方法之所以能对后生成的元素也绑定相应的事件的原因归结在“事件委托”上面,所谓

关于Web API 2.0中的Options请求返回405的问题

关于Web API 2.0中的Options请求返回405的问题 前提:IIS寄宿的网站 当你向服务器发送非简单请求时,客户端会先发送一条预检请求,借以确认当前请求源和待请求方法是否被网站允许。(关于这种Http请求的详细信息,请在道友的文章中学习) 道友的文章写的很好,其提供的解决方案是使用一个微软公司提供的官方DLL。为了不被DLL蒙在鼓里,本文提供了另外一种解决思路。 当客户端

Android的Launch

看了一下资料,其实差别并不像一般的bootloader之类那么大。基本上还是和普通的APK程序差不多,基本上是AMS启动的第一个带界面的程序,这个界面也是常规的开发模式。可以设置各种view,可以设置背景。 然后在这个程序中,可以读取已安装的各种程序,然后自己做icon或者用程序原来的icon,将它们显示在界面上。当用户点击的时候,处理点击事件,打开程序。 从界面来说这个界面就是一个Grid

spark-shell启动报错:Yarn application has already ended! It might have been killed or unable to launch...

前半部分转自:https://www.cnblogs.com/tibit/p/7337045.html (后半原创) spark-shell不支持yarn cluster,以yarn client方式启动 spark-shell --master=yarn --deploy-mode=client 启动日志,错误信息如下   其中“Neither spark.yarn.ja

NSNotification、delegate和KVO的…

1.效率肯定是delegate比nsnotification高。 2. delegate方法比notification更加直接,最典型的特征是,delegate方法往往需要关注返回值, 也就是delegate方法的结果。比如-windowShouldClose:,需要关心返回的是yes还是no。所以delegate方法往往包含 should这个很传神的词。也就是好比你做我的delegat

解决Javadoc generation failed Generated Javadoc options file

上传至jcenter时报此错误,解决方法:在项目的build.gradle的最外层加入: tasks.getByPath(":(你想要禁止的module名称,如app):javadocRelease").enabled = false 如: tasks.getByPath(":app:javadocRelease").enabled = false sync项目,OK了。

jQuery 中的 siblings 、eq、off、index、delegate

一、siblings siblings() 获得匹配集合中每个元素的同胞,通过选择器进行筛选是可选的。.siblings(selector) 如(选中中是黄色部分): <div><span>Hello</span></div>   <p class="selected">Hello Again</p>   <p>And Again</p> <script>    $("p").siblin

C++实现事件委托delegate

一、概述 用C++做项目的时候,尤其是写客户端的时候经常会有事件回调的设计,一般的方式是使用虚函数表,用一个虚基类包含一系列的回调函数。但这种方式和C++11的lamda不兼容,为了更方便的实现事件回调机制,使用delegate是很不错的一种方式。 二、源码 参考了duilib的CDelegate和C#的Deleagte<T>得出如下实现: https://download.csdn.ne

C# 委托详解(Delegate)

引言 在 C# 编程当中,委托(Delegate)是一种特殊的类型,它允许将方法作为参数传递给其他方法,或者将方法作为返回值返回,这种特性使得委托成为实现回调函数、事件处理等,所有的委托都派生自System.Delegate类。 C#中的委托类似于C 或 C++中函数的指针。委托是存在对某个方法的引用的一种引用类型变量,引用可以在运行的时候被打断,当事件出现,就必然有委托的影子,而有委托的时候

【ROS2】launch启动文件:高级

1、事件 1.1 简述 ROS2的Launch系统通过事件处理程序管理和监控用户定义的流程。 同时还负责监控流程状态并响应状态变化,这些变化称为事件。 ROS2 Launch系统中的事件,可以处理各种进程和节点状态变更,例如流程启动、IO操作、流程退出等。 注册事件处理程序,可以对这些事件进行响应。例如,当某个节点启动失败时,可以自动重启该节点或发送通知。这种能力使人们能够编写更为智能和自恢