本文转载至 http://mobile.51cto.com/iphone-464809.htm

用程序扩展最初于WWDC 2014大会上正式亮相,这是一种将iOS应用程序功能扩展至系统其它组成部分的途径、而且能够实现更为出色的跨应用通信效果。

AD:干货来了,不要等!WOT2015 北京站演讲PPT开放下载!

应用程序扩展最初于WWDC 2014大会上正式亮相,这是一种将iOS应用程序功能扩展至系统其它组成部分的途径、而且能够实现更为出色的跨应用通信效果。

举例为说,大家可以利用Today扩展创建出能够显示在通知中心之内的功能部件、Sharing扩展则帮助用户将信息共享至社交网络当中,而Action扩展的作用在于允许用户执行当前内容——包括将其以不同方式显示或者对内容作出更改。在今天的上手指南当中,我们将了解如何从零开始创建一项Action扩展。

虽然这篇文章并不会对大家的知识储备提出太多硬性要求,但我还是建议读者朋友能够首先阅读一些相关资料,从而在本文指导之后得以更轻松地掌握更多扩展创建知识。

WWDC大会演讲:为iOS及OS X创建扩展——第一部分与第二部分

应用程序扩展编程指南

1. 我们要创建什么?

我们将要创建一项名为“Read it”的简单Action扩展。这项扩展将把文本内容作为输入信息,并利用AVFoundation框架中的语音合成API将其朗读出来。我认为整个流程非常适合作为本教程的核心内容,因为在处理当中我们无需引入任何第三方依赖性、也不会产生其它难以处理的问题。

以下为我们在创建结束之后所得到的扩展功能效果。大家可以点击此处从GitHub上下载到本教程中的创建结果。

2. 创建一项Action扩展

第一步:项目设置

首先要做的是启动Xcode 6.1或者更高版本,而后创建一个新项目。在Xcode的File菜单当中选择New > Project…,然后从模板列表当中选择Single View Application。

点击Next并为我们的项目设定一个SampleActionExtensionApp名称。输入一个Organization Identifier并将Devices类型设置为iPhone。在本教程当中,我们将使用的编程语言为Objective-C。

第二步:添加目标

在完成了以上项目创建工作之后,大家接下来可以为Action扩展添加一个目标了。从File菜单下选择New > Target…。在左侧面板当中,从iOS选项处选择Application Extension,并在选定Action Extension后点击Next。

现在将Product Name设置为ReadItAction。此外还需要注意其它一些选项,特别是Action Type。我们稍后再就这一话题进行深入探讨。现在点击Finish以创建Action扩展。

现在系统会询问大家是否打算激活这套ReadItAction项目。暂时点击Cancel,因为我们之后会通过运行内容应用来安装这一Action扩展、而非直接加以激活。

Action类型

Action扩展共分为两种类型,其一配备用户界面、另一种则不配备用户界面。大家可能会觉得奇怪——不配备用户界面的Action扩展到底有什么实实在在的好处?下面就让我为大家作出解释。

不具备用户界面的Action扩展以内容变更为目标作用于当前项目。举例来说,一项Action扩展能够去除相片当中的红眼现象,而且其完全无需用户界面作为配合。内容性应用随后可以对这部分经过变更的内容加以运用,在以上实例中即为完成了修正的相片素材。

配备用户界面的Action扩展则可以表现为全屏形式或者格式表形式。Action扩展目标模板采用的是全屏幕形式,因此我们也将在接下来的创建过程中将其作为设计思路。

第三步:用户界面的实现

现在我们已经完成了基础性设置流程,也就是做好了创建用户界面的各项准备工作。下面我们将从应用程序内容开始入手。

首先点击Project Navigator当中SampleActionExtensionApp组之下的Main.storyboard。在右侧面板当中,选择File Inspector并取消对Use size classes的勾选。请注意,如果大家打算创建的是一款真正的应用程序且不需要对iPad提供支持,那么使用size classes(即尺寸类)可能会是最好的选择。

下面打开Object Library,并将文本视图与工具栏拖拽至该视图当中。在右侧的Size Inspectoron中将文本视图的框体设定为{x:8, y:20, width:304, height:288}。而对于工具栏,我们同样在Size Inspector中对其进行设置,具体参数为{x:0, y:308, width:320, height:44}。

工具栏当中应当包含一个栏按钮。将其选定,而后在Attributes Inspector当中将其Style设置为Plain,并将其Identifier设置为Action。

作为收尾工作,我们需要将文本视图当中的默认文本内容移除并替换为“Tap the action button to invoke activity view controller. Then select 'Read it' action and this text will be read by our sample Action extension.(点击action按钮以调用活动视图控制器。而后选择‘Read it’操作,这段文本将由我们的示例Action扩展朗读出来。)”

视图控制器的用户界面显示效果现在应当如下图所示:

当然,我们也可以将内容应用程序保留为空白。毕竟我们的目标在于构建一套示例性应用程序扩展,因此该应用本身并不需要真正的执行功能。不过我个人希望向大家展示从应用程序内部实现活动控制器调用有多么轻松,相信各位也能够借此了解如何将更多其它Action扩展纳入自己的应用当中。

在点击工具栏当中的按钮时,一套活动视图控制器将会显示出来,而我们则能够从这里对自己的Action扩展进行调用。选择这种方式的另一个理由在于,如果大家打算将自己的扩展发布到App Store当中,那么其必须要作为一款真正应用程序的组成部分、而应用当然得拥有功能才可以顺利通过苹果官方的审批。

第四步:当前活动视图控制器

接下来,我们需要将一部分代码添加到ViewController.m当中。首先在视图控制器的类扩展当中为文本视图创建一套外观,具体代码如下所示。

  1. @interface ViewController ()
  2. @property (nonatomic, weak) IBOutlet UITextView *textView;
  3. @end

创建一项名为actionButtonPressed的action,在这里我们将对UIActivityViewController实例进行初始化与显示、并将其提供给用户。

  1. - (IBAction)actionButtonPressed:(id)sender {
  2. UIActivityViewController *activityVC = [[UIActivityViewController alloc] initWithActivityItems:@[self.textView.text]
  3. applicationActivities:nil];
  4. [self presentViewController:activityVC animated:YES completion:nil];
  5. }

让我们再说回Main.storyboard,通过点击Control并将文本视图外观方案从View Controller Scene下的View Controller对象中将其拖拽至文本视图内、然后在弹出的菜单中选择textView,这就实现了文本视图外观与文本视图的对接。

为了与action方法实现对接,我们需要在工具当中选择该栏按钮并打开Connections Inspector。将其从Sent actions下的selector当中拖拽至View Controller对象,而后在弹出的菜单内选择actionButtonPressed:。

到这里应用程序的用户界面已经设计完成并且正式交付使用,下面我们可以继续进行Action扩展创建工作了。

第五步:用户界面的实现

在Project Navigator当中,展开ReadItAction组并点击MainInterface.storyboard。大家应该会注意到,该故事板并非空白、其中已经包含有一部分用户界面组件。我们可以对其中一部分加以利用,但具体的图象视图却帮不上什么忙。因此选定该图象视图并通过按下Delete键将其移除。

接下来打开Object Library并在下方的导航栏中添加一套文本视图。将其框体变更为{x: 8, y: 72, width: 304, height: 300}。最后,双击该导航栏的标题视图并将标题内容设定为“Text reader”。

第六步:ActionViewControlle的实现

到了这一步,我们需要搞定Action扩展的实现工作。在Project Navigator当中选择ActionViewController.m,并对其实施以下几项变更。

下面的导入语句会将一条导入语句添加到AVFoundation框架当中,这样我们就能将其语音合成API运用在自己的Action扩展当中了。

1 @import AVFoundation;

在ActionViewController类的类扩展当中,移除其中的imageView外观并添加到我们之前曾经添加至文本视图当中的新外观。

  1. @interface ActionViewController ()
  2. @property (nonatomic, strong) IBOutlet UITextView *textView;
  3. @end

除此之外,我们还需要对ActionViewController类中的viewDidLoad方法作出以下几项变更。

  1. 30 - (void)viewDidLoad {
  2. [super viewDidLoad];
  3. //从扩展背景信息中获取我们打算处理的项目。
  4. // 在我们的Action extension当中, 我们只需要一个输入项目(即文本),因此我们使用数组中的第一个项目。
  5. NSExtensionItem *item = self.extensionContext.inputItems[0];
  6. NSItemProvider *itemProvider = item.attachments[0];
  7. if ([itemProvider hasItemConformingToTypeIdentifier:(NSString *)kUTTypePlainText]) {
  8. // 这是一段纯文本!
  9. __weak UITextView *textView = self.textView;
  10. [itemProvider loadItemForTypeIdentifier:(NSString *)kUTTypePlainText options:nil completionHandler:^(NSString *item, NSError *error) {
  11. if (item) {
  12. [[NSOperationQueue mainQueue] addOperationWithBlock:^{
  13. [textView setText:item];
  14. //设置语音合成并加以启动
  15. AVSpeechSynthesizer *synthesizer = [[AVSpeechSynthesizer alloc]init];
  16. AVSpeechUtterance *utterance = [AVSpeechUtterance speechUtteranceWithString:textView.text];
  17. [utterance setRate:0.1];
  18. [synthesizer speakUtterance:utterance];
  19. }];
  20. }
  21. }];
  22. }
  23. }

整个实现过程还是非常容易理解的。在viewDidLoad当中,我们得到了输入文本内容、将其分配给文本视图、而后再创建一个能够将其朗读出来的语音合成对象。

第七步:配置Action扩展

虽然我们已经接近整个项目创建流程的尾声,但仍有一些需要着重关注的细节问题。首先,我们需要将故事板中的文本视图与我们此前已经创建完成的外观方案相对接。

打开MainInterface.storyboard并将文本视图与Image场景相对接,正如我们之前在Main.storyboard当中完成的操作一样。

接下来我们还需要为Action扩展指定所能支持的数据类型。在这一次的实例当中,我们只需要支持纯文本数据即可。展开Supporting Files组并选择Info.plist。在Info.plist当中,遵循NSExtension > NSExtensionAttributes > NSExtensionActivationRule导航流程,最后将NSExtensionActivationRule的类型由String变更为Dictionary。

在已经展开的dictionary当中,点击旁边的+号按钮,从而添加一个新的子级键。将其名称设置为NSExtensionActivationSupportsText,类型设定成Boolean,而值则取为YES。这样一来,我们就能确保自己的Action扩展只在输入项目包含文本内容时才会显示出来。

仍然是在Info.plist当中,我们要将Bundle Display Name变更为Read It。这样看起来会更加清晰。下图所示为Info.plist文件当中相关部分的设置结果:

第八步

作为画龙点睛之笔,大家可以为Action扩展添加一个图标。在Project Navigator当中,选择该项目并在目标之下选定ReadItAction目标。在App Icons and Launch Images部分中的General标签下点击App Icons Source旁边的Use Asset Catalog。根据提示,我们接下来需要点击Migrate。而后慎用至资产目录并将以下图标拖拽至iPhone App iOS 7,8 60pt 2x位置。

完成应用程序的构建与运行步骤,看看一切是否像我们预期的那样运转正常。不过还有一个需要关注的问题:如果声音图标没有被正常显示在Action扩展之内,大家需要确保主Images.xcassets文件已经被正确复制到了扩展目标当中。

要完成这项操作,我们需要在Project Navigator当中选定该项目并从Targets列表当中选择ReadItAction目标。打开屏幕顶端的Build Phases标签并展开Copy Bundle Resources步骤。如果Images.xcassets文件并未出现在资源列表当中,那么点击其中的小加号将其手动添加到列表之内。

3. 运行及测试

最后要做的就是运行应用程序并尝试其各功能的起效情况。以下显示的两幅截图为运行当中的扩展外观。大家也可以尝试通过记事本应用调用该活动视图控制器,并让我们的扩展读取之前曾经记录过的文本内容。除此之外,我们不妨在相片应用当中打开活动列表,这时大家会发现自己的扩展并没有被列中其中。没错,这正好符合我们之前为其设置的激活规则。

总结

在今天的教程当中,大家了解了如何构建一套简单的Action扩展。我们还涉及到了一些基础性知识,即如何运用AVFoundation框架当中的语音合成API。如果大家有举创建出更多扩展方案,也可以点击此处查看由Cesar Tessarin带来的Today扩展创建指南。

如果大家对本文内容还抱有任何疑问或者建议,请在下方的评论栏中与我们分享。

英文原文:http://code.tutsplus.com/tutorials/ios-8-how-to-build-a-simple-action-extension--cms-2279

iOS 8出色的跨应用通信效果:解读Action扩展的更多相关文章

  1. 通信服务器群集——跨服务器通信Demo(源码)

    对于一些基于TCP Socket的大型C/S应用来说,能进行跨服务器通信可能是一个绕不开的功能性需求.出现这种需求的场景类似于下面描述的这种情况. 假设,我们一台TCP应用服务器能同时承载10000人 ...

  2. 【JavsScript】父子页面之间跨域通信的方法

    由于同源策略的限制,JavaScript跨域的问题,一直是一个比较棘手的问题,为了解决页面之间的跨域通信,大家煞费苦心,研究了各种跨域方案.之前也有小网同学分享过一篇“跨域,不再纠结” 开始照着尝试时 ...

  3. 【JavaScript】父子页面之间跨域通信的方法

    由于同源策略的限制,JavaScript跨域的问题,一直是一个比较棘手的问题,为了解决页面之间的跨域通信,大家煞费苦心,研究了各种跨域方案.之前也有小网同学分享过一篇“跨域,不再纠结” 开始照着尝试时 ...

  4. 使用 JSONP 实现跨域通信

    简介 Asynchronous JavaScript and XML (Ajax) 是驱动新一代 Web 站点(流行术语为 Web 2.0 站点)的关键技术.Ajax 允许在不干扰 Web 应用程序的 ...

  5. 跨进程通信之Messenger

    1.简介 Messenger,顾名思义即为信使,通过它可以在不同进程中传递Message对象,通过在Message中放入我们需要的入局,就可以轻松实现数据的跨进程传递了.Messenger是一种轻量级 ...

  6. linux模拟实现主机跨路由通信

    p.MsoNormal,li.MsoNormal,div.MsoNormal { margin: 0cm; margin-bottom: .0001pt; text-align: justify; f ...

  7. 【朝花夕拾】Android性能篇之(七)Android跨进程通信篇

    前言 只要是面试高级工程师岗位,Android跨进程通信就是最受面试官青睐的知识点之一.Android系统的运行由大量相互独立的进程相互协助来完成的,所以Android进程间通信问题,是做好Andro ...

  8. [转]html5: postMessage解决跨域和跨页面通信的问题

    [转]html5: postMessage解决跨域和跨页面通信的问题 平时做web开发的时候关于消息传递,除了客户端与服务器传值,还有几个经常会遇到的问题: 多窗口之间消息传递(newWin = wi ...

  9. Docker容器跨主机通信之:直接路由方式

    一.Docker网络基本原理 直观上看,要实现网络通信,机器需要至少一个网络接口(物理接口或虚拟接口)与外界相通,并可以收发数据包:此外,如果不同子网之间要进行通信,需要额外的路由机制. Docker ...

随机推荐

  1. Windows2008 R2下,应用程序池 'XXXXXXXX' 被自动禁用,原因是为此应用程序池提供服务的进程中出现一系列错误。

    转:http://www.cnblogs.com/freeton/archive/2012/08/28/2660585.html http://www.hack001.com/post/151

  2. TFS2013以独占的方式签出

  3. JAVA学习第三十二课(经常使用对象API)- 基本数据类型对象包装类

    将基本数据类型(8种:int..)封装成对象的优点就是能够在对象中封装很多其它的功能和方法来操控该数据 常见的操作就是:用于基本数据类型与字符串之间的转换 基本数据类型对象包装类一般用于基本类型和字符 ...

  4. C# AutoResetEvent

    文章转载自:C# AutoResetEvent AutoResetEvent 常常被用来在两个线程之间进行信号发送 AutoResetEvent是.net线程简易同步方法中的一种,两个线程共享相同的A ...

  5. jQuery MiniUI自定义单元格

    监听处理"drawcell"事件 使用"drawcell"事件,可以自定义单元格内容.样式.行样式等. grid.on("drawcell" ...

  6. tesseract中文语言文件包 下载

    tesseract中文语言文件包 下载 tesseract中文语言文件包 下载 tesseract中文语言文件包 下载 下载地址是:https://github.com/tesseract-ocr/l ...

  7. laravel多条件查询,及分页

    $res = DtkModel::where('ID','>','1')->select("ID")->get()->paginate(20);//不成立 ...

  8. [docker]存储驱动overlay和overlay2的区别

    overlay和overlay2的区别 参考:http://blog.csdn.net/styshoo/article/details/60715942 docker pull ubuntu 本质区别 ...

  9. Codeforces Round #235 (Div. 2) C. Team

    C. Team time limit per test 1 second memory limit per test 256 megabytes input standard input output ...

  10. 使用vs2015编译器编译libpqxx时发生的错误以及解决办法

    d:\libpqxx-4.0\libpqxx-4.0\src\strconv.cxx(195): error C2440: “=”: 无法从“std::basic_istream<char,st ...