【iOS扩展开发攻略】Action Extension
上一篇《iOS扩展开发攻略:Share Extension》介绍了分享扩展的开发与使用,本篇主要还是讲述在系统分享菜单中最底下一栏的功能扩展:Action Extension,该扩展跟Share Extension实现比较类似只是在使用场景上进行了区分,Share Extension主要用于将Host应用中的内容分享到Container应用中,而Action Extension则主要用于将Host应用中的内容进行对应处理,原则上来说作用范围比Share Extension要广。
那么,下面将详细讲解开发Action Extension具体的操作步骤:
1. 创建Action Extension扩展Target
1、打开项目设置,在TARGETS侧栏地下点击“+”号来创建一个新的Target,如图:
2、然后选择”iOS” -> “Application Extension” -> “Action Extension”,点击“Next”。如图:
3、给扩展起个名字,这里填写了“Action”,然后要注意Action Type这里有两个选项:** Presents User Interface 和 No User Interface **。前者是触发扩展后会弹出一个UI界面,后者是不带界面的扩展。这里我会分两部分进行讲解,先从无UI的扩展开始,所以选择了No User Interface,点解Finish完成创建。如图:
4、这时候会提示创建一个Scheme,点击“Activate”。如图:
一个无UI的Action Extension Target到此已经创建完成了。下面先来看一下新建的扩展结构,如下图所示:
扩展的文件组织结构描述如下:
文件 | 说明 |
---|---|
ActionRequestHandler.h | 扩展处理类的头文件,对处理类型的声明描述。 |
ActionRequestHandler.m | 扩展处理类的实现文件,处理扩展实际的业务逻辑。 |
Action.js | 与Web也进行交互的脚本,后续会详细介绍它的作用。 |
Info.plist | 扩展的配置文件 |
先Command+R编译运行默认的扩展来看一下实际效果。
可以看到在弹出的分享菜单的底下一栏多了一个叫Action的小图标(演示图1),并且点击后网页的背景颜色变成红色(演示图2)。下面将对这个例子进行详细的讲解。
2. 分析扩展例子代码
先打开ActionRequestHandler.h头文件,可以看到扩展的处理类ActionRequestHandler
的定义,代码如下:
@interface ActionRequestHandler : NSObject <NSExtensionRequestHandling>
@end
上面的类型实现了一个NSExtensionRequestHandling
的协议。这也是无UI的扩展对象必须要实现的协议,否则无法向处理类返回正确的回调。我们可以看一下协议的声明:
@protocol NSExtensionRequestHandling <NSObject>
@required
- (void)beginRequestWithExtensionContext:(NSExtensionContext*)context;
@end
协议只有一个方法beginRequestWithExtensionContext:
,就是点击扩展图标的时候就会触发这个方法,并将扩展的上下文作为参数进行回调(关于NSExtensionContext相关内容在《iOS扩展开发攻略:Share Extension》有讲述)。所以无UI的扩展相对来说比较简单,只要实现这个方法的处理即可。下面就来看一下例子中的.m文件是怎么处理的。
- (void)beginRequestWithExtensionContext:(NSExtensionContext *)context {
// Do not call super in an Action extension with no user interface
self.extensionContext = context;
BOOL found = NO;
// Find the item containing the results from the JavaScript preprocessing.
for (NSExtensionItem *item in self.extensionContext.inputItems) {
for (NSItemProvider *itemProvider in item.attachments) {
if ([itemProvider hasItemConformingToTypeIdentifier:(NSString *)kUTTypePropertyList]) {
[itemProvider loadItemForTypeIdentifier:(NSString *)kUTTypePropertyList options:nil completionHandler:^(NSDictionary *dictionary, NSError *error) {
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
[self itemLoadCompletedWithPreprocessingResults:dictionary[NSExtensionJavaScriptPreprocessingResultsKey]];
}];
}];
found = YES;
}
break;
}
if (found) {
break;
}
}
if (!found) {
// We did not find anything
[self doneWithResults:nil];
}
}
从上面代码可知,扩展是通过匹配上下文(NSExtensionContext
)的inputItem的附件(attachment)类型是否为PropertyList。然后再通过loadItemForTypeIdentifier
方法加载附件后进行相应的处理(关于NSExtensionItem相关内容在《iOS扩展开发攻略:Share Extension》有讲述)。其中处理方法itemLoadCompletedWithPreprocessingResults
代码如下:
- (void)itemLoadCompletedWithPreprocessingResults:(NSDictionary *)javaScriptPreprocessingResults {
if ([javaScriptPreprocessingResults[@"currentBackgroundColor"] length] == 0) {
// No specific background color? Request setting the background to red.
[self d