App Programming Guide for iOS -> 应用间通信

应用只能间接的和设备上的其他应用进行通信。你可以使用AirDrop来与其他应用共享文件和数据。你也可以定义一个自定义URL方案,以便应用能使用URL向其他应用发送信息。

注意:你还可以使用UIDocumentInteractionController对象或文档拾取器来在应用间发送文件。关于添加对文件交互控制器的支持的信息,参见Document Interaction Programming Topics for iOS。关于使用文档拾取器打开文件的信息,参见Document Picker Programming Guide。

支持AirDrop

AirDrop让你可以和附近的设备共享照片、文档、URLs、以及其他类型的数据。AirDrop利用点对点网络来查找附近的设备并与它们连接。

发送文件和数据到其他应用

为了使用AirDrop发送文件和数据,使用UIActivityViewController对象从使用中的用户界面显示一个活动表。当创建这个视图控制器的时候,指定你想要共享的数据对象。这个视图控制器仅显示支持指定数据的活动。对于AirDrop,你可以指定图片、字符串、URLs、以及集中其他类型的数据。你还可以传递采用UIActivityItemSource协议的自定义对象。

为了显示活动视图控制器,你可以使用类似代码清单6-1的代码来实现。这个活动视图控制器自动使用特定对象的类型来决定什么活动显示在活动表。你不必明确指定AirDrop的活动。但是,你可以使用视图控制器的excludedActivityTypes属性来防止显示特定类型表单。当在iPad上显示一个活动视图控制器,你必须使用popover。

代码清单6-1 在iPhone上显示一个活动表单

- (void)displayActivityControllerWithDataObject:(id)obj {

   UIActivityViewController* vc = [[UIActivityViewController alloc]

                                initWithActivityItems:@[obj] applicationActivities:nil];

    [self presentViewController:vc animated:YES completion:nil];

}

更多关于使用活动视图控制器的信息,参见UIActivityViewController Class Reference。有关活动以及它所支持的数据类型的完整列表,参见UIActivity Class Reference。

接收发送到应用的文件和数据

想要使用AirDrop接收发送到应用的文件,需要做如下操作:

  • 在Xcode中,声明对应用能够打开的文档类型支的持。
  • 在应用的委托中,实现application:openURL:sourceApplication:annotation:方法,使用这个方法来接收被其他应用发送来的数据。

Xcode项目的Info选项卡包含一个Document Types部分,它用于指定应用支持的文档类型。至少,你必须指定文档类型的名称,以及一个或多个表示数据类型的UTI。例如,想要声明支持PNG文件,你将把public.png设置为UTI字符串。iOS使用特定的UTI来确定应用是否有资格打开给定的文档。

在把符合条件的文档转移到应用的容器之后,iOS启动应用(如有必要)并调用应用委托的application:openURL:sourceApplication:annotation:方法。如果应用在前台,你将使用这个方法来打开这个文件,并显示给用户。如果应用在后台,你只需要确定该文件在那里,以便你以后打开它。因为文件通过AirDrop传输是使用数据保护加密的,所以除非设备解锁否则你无法打开文件。

应用可以读取和删除它接收到的文件,但是它不可以对文件进行修改。如果你计划修改文件,你必须先把它从当前位置移出去。建议删除后续文件的原始版本

使用URL方案(Schema)实现应用间通信

URL方案让你可以通过你定义的协议来实现应用间的通信。想要与实现这个方案的应用进行通信,你必须常见恰当格式的URL并请求系统打开它。为了实现支持自定义方案,你必须声明支持这个方案,并处理使用该方案传入的URL

注意:苹果为 http, mailto, tel, 以及 sms 等URL方案提供内建支持。它还支持针对Maps、YouTube、以及iPod应用的基于http的URL。这些方案的处理器时固定的不能修改。如果你的URL类型包含与苹果定义的相同的方案,苹果提供的应用会代替你的应用启动。关于苹果支持的方案的信息,参见Apple URL Scheme Reference。

发送URL到其他应用

当你向发送数据到一个实现了自定义URL方案的应用,创建一个合适格式的URL,并调用该应用对象的openURL:方法。openURL:方法使用注册的方案启动该应用,并把你的URL传递给它。此时,控制权传递给了新应用。

以下代码片段说明一个应用如何能够请求另一个应用的服务(这个例子中的“todolist”是假定的应用注册的自定义方案):

NSURL *myURL = [NSURL URLWithString:@"todolist://www.acme.com?Quarterly%20Report#200806231300"];

[[UIApplication sharedApplication] openURL:myURL];

如果你的应用定义了一个自定义的URL方案,它应该实现该方案的处理器,如同Implementing Custom URL Schemes中描述的那样。更多关于系统支持的URL方案的信息,参见Apple URL Scheme Reference。

实现在定义URL方案

如果你的应用接收特定格式的URL,你应该利用系统注册合适的URL方案。应用经常使用自定义的URL方案来向其他应用提供服务。例如,Maps应用支持显示特定地图位置的URL。

注册自定义URL方案

想要给应用注册一个URL类型,请在应用的Info.plist文件中包含 CFBundleURLTypes键。 CFBundleURLTypes键包含一个字典数组,每个字典都定义了一个应用支持的URL方案。表6-1描述了每个字典包含的键和值。

表6-1 CFBundleURLTypes属性的键和值

CFBundleURLName 包含URL抽象名字的字符串。想要确保唯一性,建议使用反向DNS风格的标识符,例如com.acme.myscheme。
你指定的字符串也用于应用的InfoPlist.strings文件中的键。这个键的值是人可读的方案名。
CFBundleURLSchemes 一个包含URL方案名的字符串数组—— 例如http, mailto, tel, 和 sms.

注意:如果多个第三方应用被注册用来处理同一个URL方案,则目前还没有确定哪个应用将被分配给该方案。

拥有自己自定义URL方案的应用,必须能够处理传入的URL。所有URLs都会在启动时或者应用在后台运行时被传递给应用委托。为了处理传入的URL,你的委托应该实现下面两个方法:

  • 使用application:willFinishLaunchingWithOptions:和application:didFinishLaunchingWithOptions:方法来取回关于URL的信息,并决定是否打开它。如果两个方法都返回NO,应用的URL处理代码不会被调用。
  • 使用application:openURL:sourceApplication:annotation:方法打开文件。

如果当URL请求到达时应用没有在运行,它将启动并进入前台,以便能够打开URL。application:willFinishLaunchingWithOptions: 或 application:didFinishLaunchingWithOptions:方法的实现可以从选项字典中取回URL,并确定应用是否可以它开它。如果能,返回YES,让application:openURL:sourceApplication:annotation: (或 application:handleOpenURL:)方法处理URL的打开。(如果你两个方法都实现了,那么两个都要返回YES。)图6-1显示了请求打开URL的应用的启动顺序。

图6-1 启动应用来打开一个URL

如果当URL请求到达的时候应用在后台运行或是被挂起,它会进入前台并打开URL。此后不久,系统会调用委托的application:openURL:sourceApplication:annotation方法来检查URL并打开它。图6-2战士了应用进入前台代开URL的过程。

图6-2 唤醒后台应用来打开URL

注意:支持自定义URL方案的应用在启动应用来处理URL的时候,能指定不同的启动图片来显示。更多关于如何指定这些启动图片的信息,参见Displaying a Custom Launch Image When a URL is Opened。

所有被传递到应用的URL都是以NSURL对象的形式存在的。你可以定义自己的URL格式,但是NSURL类符合 RFC 1808规范,因此支持大多数URL格式约定。具体来说,这个类包括了一系列方法,它们返回URL的各个部分,包括用户、密码、查询、片段、以及参数字符串等。你自定义方案的“协议”能使用URL的这些部分来传达个钟信息。

在代码清单6-2中展示了application:openURL:sourceApplication:annotation:方法的实现,把传入URL的特定信息传递给应用。这个委托提取这些信息(在本例中是to-do任务类型以及任务到期时间),并创建应用的模型对象。这个例子嘉定用户使用的是格里高利日历。如果应用支持非格里高利日历,你需要设计你的URL方案,并准备好处理代码中的其他日历的类型。

代码清单6-2 基于自定义方案处理URL请求

- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url

        sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {

    if ([[url scheme] isEqualToString:@"todolist"]) {

        ToDoItem *item = [[ToDoItem alloc] init];

        NSString *taskName = [url query];

        if (!taskName || ![self isValidTaskString:taskName]) { // must have a task name

            return NO;

        }

        taskName = [taskName stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

 

        item.toDoTask = taskName;

        NSString *dateString = [url fragment];

        if (!dateString || [dateString isEqualToString:@"today"]) {

            item.dateDue = [NSDate date];

        } else {

            if (![self isValidDateString:dateString]) {

                return NO;

            }

            // format: yyyymmddhhmm (24-hour clock)

            NSString *curStr = [dateString substringWithRange:NSMakeRange(0, 4)];

            NSInteger yeardigit = [curStr integerValue];

            curStr = [dateString substringWithRange:NSMakeRange(4, 2)];

            NSInteger monthdigit = [curStr integerValue];

            curStr = [dateString substringWithRange:NSMakeRange(6, 2)];

            NSInteger daydigit = [curStr integerValue];

            curStr = [dateString substringWithRange:NSMakeRange(8, 2)];

            NSInteger hourdigit = [curStr integerValue];

            curStr = [dateString substringWithRange:NSMakeRange(10, 2)];

            NSInteger minutedigit = [curStr integerValue];

 

            NSDateComponents *dateComps = [[NSDateComponents alloc] init];

            [dateComps setYear:yeardigit];

            [dateComps setMonth:monthdigit];

            [dateComps setDay:daydigit];

            [dateComps setHour:hourdigit];

            [dateComps setMinute:minutedigit];

            NSCalendar *calendar = [s[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];

            NSDate *itemDate = [calendar dateFromComponents:dateComps];

            if (!itemDate) {

                return NO;

            }

            item.dateDue = itemDate;

        }

 

        [(NSMutableArray *)self.list addObject:item];

        return YES;

    }

    return NO;

}

一定要验证从URL传入到应用的输入;查看 Secure Coding Guide中的Validating Input and Interprocess Communication ,来查找如何避免与URL处理相关的问题。想要学习关于苹果定义的URL方案,参见Apple URL Scheme Reference。

当URL被打开的时候显示自定义启动图片

应用支持自定义URL方案能给每个方案提供各自的自定义启动图片。当系统启动应用来处理URL的时候,并灭有相关的快照可用,它显示的是你指定的启动图片。想要指定启动图片,提供用下面的命名约定来命名的PNG格式的图片。

在这个命名约定中,basename表示基础图像名,这个图像名是在Info.plist文件中的由UILaunchImageFile键指定的。如果你不指定一个自定义的基础名字,系统会使用字符串Default。<url_scheme>部分是你的URL方案名。要想为myapp的URL方案指定一个通用的启动图片,你应该在应用程序束当中包含一个名字为Default-myapp@2x.png的图片文件。(@2x修饰符表示该图像用于Retina显示屏。如果你的应用也支持标准分辨率的显示器,你应该还要提供Default-myapp.png图像。)

关于你能包含在启动图片名字中的其他修饰符的信息,参见Information Property List Key Reference中UILaunchImageFile键的描述。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 156,757评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,478评论 1 289
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,540评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,593评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,903评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,329评论 1 210
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,659评论 2 309
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,383评论 0 195
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,055评论 1 238
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,337评论 2 241
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,864评论 1 256
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,227评论 2 251
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,820评论 3 231
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,999评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,750评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,365评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,260评论 2 258

推荐阅读更多精彩内容

  • 应用间通信 应用程式只能间接与设备上的其他应用进行通信。您可以使用AirDrop与其他应用程序共享文件和数据。您还...
    nicedayCoco阅读 671评论 0 1
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,087评论 18 139
  • 这是阅读该指南的一些笔记,说说是笔记,其实就是把一些自己决定重要的知识给翻译了一遍,因为英文读着读着就把前面的给忘...
    没阳光的午后阅读 3,012评论 6 45
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 170,544评论 25 707
  • 《必定会有一辆火车,从南开到北》 文/江海 必定会有一辆火车,从南开到北 穿越大半个中国,找到我和你 在黄昏时出发...
    停笔阅读 599评论 7 8