iOS 8应用程序扩展教程

本文概述

  • 什么是iOS 8应用扩展程序以及它们如何工作?
  • 生命周期
  • 创建应用程序扩展-使用Today扩展的动手示例
  • 技术说明
  • 总结
很少有人尝试过(请看一下), 但是定义了智能手机和移动操作系统外观的是第一台iPhone的Apple。苹果在硬件和用户体验方面取得了令人难以置信的突破。但是, 我们经常忘记, 它们还为移动操作系统的工作方式以及智能手机应用程序的制作方式设定了标准。
在应用程序之间建立混凝土墙, 使它们完全隔离并且彼此之间不被察觉, 是确保它们安全和保护数据的最佳方法。所有活动均受到iOS的严格监控, 并且应用程序在其范围之外只能执行少数操作。
“ 节制是最好的保护!” -但是有趣的地方在哪里?
他们花了一段时间。如果你问我, 时间太长了, 但是有了iOS 8, Apple决定找点乐子。 iOS 8引入了一个名为App Extensions的新概念。这项新功能并未打破应用程序之间的壁垒, 但它打开了几扇门, 在某些应用程序之间提供了温和而切实的联系。最新的更新为iOS开发人员提供了自定义iOS生态系统的选项, 我们也渴望看到这条路也将打开。
iOS 8应用程序扩展教程

文章图片
什么是iOS 8 App Extensions, 它们如何工作? 简而言之, iOS 8 App Extensions提供了一种与应用程序交互的新方法, 而无需启动它或将其显示在屏幕上。
正如预期的那样, Apple确保将其放在一切之上, 因此你的应用程序可以提供一些新的切入点:
  • 今日(也称为窗口小部件)-通知中心的” 今日” 视图中显示的扩展名显示简要信息并允许执行快速任务。
  • 共享-一种扩展, 使你的应用可以与社交网络和其他共享服务上的用户共享内容。
  • 操作-一种扩展, 它允许在” 操作” 表中创建自定义操作按钮, 以允许用户查看或转换源自主机应用程序的内容。
  • 照片编辑-一种扩展, 允许用户在” 照片” 应用中编辑照片或视频。
  • 文档提供程序-用于允许其他应用程序访问由你的应用程序管理的文档的扩展。
  • 自定义键盘-替代系统键盘的扩展名。
应用扩展程序不是独立的应用程序。它们提供了应用程序的扩展功能(可以从称为主机应用程序的其他应用程序中访问), 该功能旨在提高效率并专注于单个任务。它们具有自己的二进制文件, 代码签名和元素集, 但作为包含的应用程序二进制文件的一部分通过App Store交付。一个(包含)应用程序可以具有多个扩展。用户安装了具有扩展程序的应用程序后, 即可在iOS上使用。
让我们看一个例子:一个用户使用Safari找到一张图片, 点击” 共享” 按钮, 然后选择要共享的应用程序扩展名。 Safari与iOS社交框架” 对话” , 该框架加载并显示了扩展。扩展程序的代码运行, 使用系统的实例化通信通道传递数据, 完成任务后-Safari拆除了扩展程序视图。此后不久, 系统终止该过程, 并且你的应用程序从未显示在屏幕上。然而, 它完成了图片共享功能。
使用进程间通信的iOS是负责确保主机应用程序和应用程序扩展可以一起工作的一种程序。开发人员使用扩展点和系统提供的高级API, 因此他们不必担心底层的通信机制。
生命周期
iOS 8应用程序扩展教程

文章图片
应用扩展程序的生命周期与iOS应用程序不同。主机应用程序启动了扩展程序的生命周期, 以响应用户的操作。然后, 系统实例化应用程序扩展, 并在它们之间建立通信通道。使用主机应用程序请求中接收的项目, 扩展程序的视图显示在主机应用程序的上下文中。显示扩展程序的视图后, 用户即可与其进行交互。为响应用户的操作, 扩展程序通过立即执行/取消任务或在必要时启动后台进程来执行任务来完成主机应用程序的请求。此后, 主机应用程序拆下了扩展程序的视图, 用户返回了主机应用程序中的先前上下文。完成该过程后, 可以将执行此过程的结果返回给主机应用。扩展程序通常会在完成从主机应用程序收到的请求后立即终止(或启动后台进程执行该请求)。
系统从主机应用程序打开用户操作的扩展程序, 该扩展程序显示用户界面, 执行一些工作, 然后将数据返回到主机应用程序(如果适合该扩展程序的类型)。扩展程序运行时, 包含的应用程序甚至没有运行。
创建应用程序扩展-使用Today扩展的动手示例 今日扩展程序(也称为窗口小部件)位于通知中心的” 今日” 视图中。它们是为用户呈现最新内容(例如显示天气状况)或执行快速任务(例如在待办事项列表应用的小部件中标记已完成的工作)的好方法。我必须在这里指出, 不支持键盘输入。
iOS 8应用程序扩展教程

文章图片
让我们创建一个Today扩展程序, 该扩展程序将显示来自我们的应用程序的最新信息(GitHub上的代码)。为了运行此代码, 请确保已为项目配置了(重新)应用组(选择你的开发团队, 请记住应用组名称必须唯一, 并遵循Xcode的说明)。
iOS 8应用程序扩展教程

文章图片
iOS 8应用程序扩展教程

文章图片
iOS 8应用程序扩展教程

文章图片
创建一个新的小部件
就像我们之前说过的, 附加应用信息并不是独立的应用。我们需要一个包含应用程序, 并在其上构建应用程序扩展。有了包含应用程序后, 我们选择通过导航到File-> New-> Target into Xcode添加一个新目标。在这里, 我们为新目标选择模板, 以添加” 今日扩展” 。
iOS 8应用程序扩展教程

文章图片
在下一步中, 我们可以选择我们的产品名称。该名称将显示在通知中心的” 今日” 视图中。在这一步中, 也可以选择在Swift和Objective-C之间选择语言。完成这些步骤后, Xcode将创建Today模板, 该模板为主体类(名为TodayViewController)提供默认的标头和实现文件, 以及Info.plist文件和界面文件(情节提要或.xib文件)。默认情况下, Info.plist文件如下所示:
< key> NSExtension< /key> < dict> < key> NSExtensionMainStoryboard< /key> < string> MainInterface< /string> < key> NSExtensionPointIdentifier< /key> < string> com.apple.widget-extension< /string> < /dict>

如果你不想使用模板提供的情节提要, 请删除NSExtensionMainStoryboard键, 然后添加带有视图控制器名称作为值的NSExtensionPrincipalClass键。
今日小部件应:
  • 确保内容始终保持最新
  • 适当响应用户交互
  • 表现良好(iOS小部件必须明智地使用内存, 否则它们将被系统终止)
共享数据和共享容器
应用程序扩展及其包含的应用程序都可以访问其私有定义的共享容器中的共享数据, 这是包含应用程序与扩展程序之间进行间接通信的一种方式。
你不只是喜欢Apple如何使这些事情变得” 简单” ? ??
通过NSUserDefaults共享数据很简单, 并且是一个常见的用例。默认情况下, 扩展程序及其包含的应用程序使用单独的NSUserDefaults数据集, 并且无法访问彼此的容器。为了更改此行为, iOS引入了应用程序组。在包含应用程序和扩展名上启用应用程序组后, 可以使用[[NSUserDefaults alloc] initWithSuiteName:@” group.yourAppGroupName” ]来访问同一共享容器, 而不是使用[NSUserDefaults standardUserDefaults]。
更新小部件
为了确保内容始终是最新的, Today扩展提供了一个API, 用于管理小部件的状态和处理内容更新。系统偶尔会捕获小部件视图的快照, 因此当小部件可见时, 将显示最新快照, 直到将其替换为实时版本的视图为止。遵守NCWidgetProviding协议对于在拍摄快照之前更新窗口小部件的状态非常重要。当小部件收到widgetPerformUpdateWithCompletionHandler:调用后, 应使用最新的内容更新小部件的视图, 并使用以下用于描述更新结果的常量之一调用完成处理程序:
  • NCUpdateResultNewData-新内容需要重绘视图
  • NCUpdateResultNoDate-窗口小部件不需要更新
  • NCUpdateResultFailed-更新过程中发生错误
- (void)widgetPerformUpdateWithCompletionHandler:(void (^)(NCUpdateResult))completionHandler { // Perform any setup necessary in order to update the view.// If an error is encountered, use NCUpdateResultFailed // If there's no update required, use NCUpdateResultNoData // If there's an update, use NCUpdateResultNewData[self updateTableView]; completionHandler(NCUpdateResultNewData); }

控制小部件何时可见
若要控制何时显示窗口小部件, 请使用NCWidgetController类中的setHasContent:forWidgetWithBundleIdentifier:方法。通过此方法, 你可以指定小部件内容的状态。可以从小部件或其包含的应用程序(如果已激活)中调用它。你可以将NO或YES标志传递给此方法, 以定义窗口小部件内容是否准备就绪。如果内容尚未准备就绪, 则在” 今日” 视图打开时, iOS将不会显示你的小部件。
NCWidgetController *widgetController = [[NCWidgetController alloc] init]; [widgetController setHasContent:YES forWidgetWithBundleIdentifier:@"com.your-company.your-app.your-widget"];

从小部件打开包含应用程序
Today小部件是唯一可以通过调用openURL:completionHandler:方法来请求打开其包含的应用程序的扩展。为确保包含应用程序的打开方式在用户当前任务的上下文中有意义, 应定义一个自定义URL方案(小部件和包含应用程序都可以使用)。
[self.extensionContext openURL:[NSURL URLWithString:@"customURLsheme://URLpath"] completionHandler:nil];

用户界面注意事项
在设计窗口小部件时, 请利用UIVisualEffectView类, 请记住必须将应模糊/鲜艳的视图添加到contentView而不是直接添加到UIVisualEffectView。窗口小部件(符合NCWidgetProviding协议)应在viewWillAppear:中加载缓存的状态, 以匹配上一个viewWillDisappear:中的视图状态, 然后在到达时平稳过渡到新数据, 而普通视图则不会这样控制器(在viewDidLoad中设置UI, 并在viewWillAppear中处理动画和加载数据)。窗口小部件应设计用于执行任务, 或单击以打开包含的应用程序。键盘条目在小部件中不可用。这意味着不应使用任何需要输入文本的UI。
无法将滚动条添加到垂直和水平滚动条中。或者更确切地说, 可以添加滚动视图, 但是滚动不起作用。 Today扩展中滚动视图中的水平滚动手势将被通知中心拦截, 这将导致从Today滚动到通知中心。垂直滚动” 今日” 扩展程序内的滚动视图将通过滚动” 今日视图” 而中断。
技术说明 在这里, 我将指出创建应用扩展程序时要记住的一些重要事项。
所有扩展共同的功能
以下各项对于所有扩展都是正确的:
  • sharedApplication对象已超出限制:应用程序扩展无法访问sharedApplication对象, 或使用与该对象相关的任何方法。
  • 摄像头和麦克风已超出限制:应用扩展程序无法访问设备上的摄像头或麦克风(但并非所有硬件元素都属于这种情况)。这是某些API不可用的结果。要访问应用程序扩展中的某些硬件元素, 你必须检查其API是否可用于应用程序扩展(通过上述API可用性检查)。
  • 大多数后台任务都超出了限制:应用扩展程序无法执行长时间运行的后台任务, 只有启动上载或下载除外, 这将在下面进行讨论。
  • AirDrop不受限制:应用扩展程序无法使用AirDrop接收(但可以发送)数据。
在后台上传/下载
可以在后台执行的一项任务是使用NSURLSession对象上载/下载。
启动上传/下载任务后, 扩展程序可以完成主机应用程序的请求并被终止, 而不会影响任务的结果。如果扩展程序在后台任务完成时尚未运行, 则系统会在后台启动包含应用程序, 并调用该应用程序的委托方法application:handleEventsForBackgroundURLSession:completionHandler:。
扩展程序启动后台NSURLSession任务的应用程序必须设置一个共享容器, 包含该应用程序及其扩展程序都可以访问该容器。
确保为包含的应用及其每个应用扩展创建不同的后台会话(每个后台会话应具有唯一的标识符)。这很重要, 因为一次只能有一个进程使用后台会话。
行动与分享
从编码人员的角度来看, Action和Share扩展之间的差异尚不完全清楚, 因为实际上它们非常相似。共享扩展目标的Xcode模板使用SLComposeServiceViewController, 它提供了可用于社交共享的标准撰写视图UI, 但这不是必需的。共享扩展也可以直接从UIViewController继承以进行完全自定义设计, 就像Action扩展可以从SLComposeServiceViewController继承一样。
这两种类型的扩展之间的区别在于使用它们的方式。使用Action扩展, 你可以构建没有自己的UI的扩展(例如, 用于翻译所选文本并将翻译返回到主机应用的扩展)。共享扩展程序使你可以直接从主机应用程序共享评论, 照片, 视频, 音频, 链接等。 UIActivityViewController同时驱动Action和Share扩展, 其中Share扩展在上一行显示为彩色图标, 而Action扩展在下一行显示为单色图标(图像2.1)。
禁止的API
不能使用头文件中带有NS_EXTENSION_UNAVAILABLE宏或不可用的类似宏标记的API(例如:iOS 8中的HealthKit和EventKit UI框架不适用于任何应用程序扩展)。
如果要在应用程序和扩展之间共享代码, 则必须记住, 即使引用不允许该应用程序扩展的API, 也会导致应用商店拒绝你的应用。你可以选择通过将共享类重构为具有公共父级和针对不同目标的不同子类的层次结构来解决此问题。另一种方法是通过#ifdef检查使用预处理器。因为仍然没有内置目标条件, 所以你必须创建自己的条件。
另一个不错的方法是创建自己的嵌入式框架。只需确保它不包含扩展程序不可用的任何API。要配置应用扩展程序以使用嵌入式框架, 请导航至目标的构建设置, 然后将” 仅要求应用扩展安全API” 设置设为” 是” 。配置Xcode项目时, 在” 复制文件” 构建阶段, 必须选择” Frameworks” 作为嵌入式框架的目标。如果选择” SharedFrameworks” 目标, 则App Store将拒绝你的提交。
向后兼容性说明
尽管仅从iOS 8开始才提供应用程序扩展, 但是你可以使包含的应用程序可用于iOS的早期版本。
苹果人机界面合规性
设计应用程式扩充功能时, 请注意Apple的iOS《人机介面指南》。无论所含应用程序支持哪种设备, 都必须确保你的应用程序扩展名是通用的。为确保应用程序扩展名是通用的, 请使用Xcode中的目标设备系列构建设置指定” iPhone / iPad” 值(有时称为通用)。
总结 【iOS 8应用程序扩展教程】应用程序扩展无疑在iOS 8中具有最明显的影响。由于79%的设备已经在使用iOS 8(根据2015年4月13日App Store的评估), 应用程序扩展是应用程序应利用的不可思议的功能。通过结合API的限制以及扩展与其包含的应用之间共享数据的方式, Apple似乎在不损害其安全模型的情况下解决了对该平台最大的抱怨之一。第三方应用程序仍然无法彼此直接共享其数据。尽管这是一个非常新的概念, 但看起来很有希望。

    推荐阅读