如何在Swift中创建Action扩展
发布日期:2021-09-29 09:56:27 浏览次数:1 分类:技术文章

本文共 5106 字,大约阅读时间需要 17 分钟。

原始链接:http://www.cocoachina.com/ios/20140923/9723.html

我们先想象一下,我们已经有一个很牛逼的应用了,我们姑且叫做重要信息记事本。它的功能就是将我们认为是重要的信息记录下,便于我们随时查看。那么何为重要信息呢?重要信息可以是很多类型的信息,比如武功秘籍、食谱、生日、一段牛逼的代码等等。当我们已经有了这样一个应用后,接下来应该考虑的事情就是如何记录重要信息了。通常思维下,你们可能认为应该是先打开这个应用,然后将重要信息敲进去。是这样么?你当用户是傻子么,什么年代了还手敲,简直弱爆了。下面我向你们介绍一个很酷的方法,那就是通过Action扩展,将信息记录到我们的应用中。下面例子的主要功能是将Safari浏览的网页中的信息保存在我们应用中。

见证奇迹的时刻

先通过File > New > Project菜单创建一个新的工程,选择Single View Application:

01.png

然后通过File > New > Target菜单给给工程添加一个Target,选择Action Extension:

02.png

在创建Action扩展时需要指定一个Aciton类型,Apple提供了两种Action扩展的类型模板。一种是有用户界面的类型,包含一个UIViewController和一个Storeboard文件,可以自定义显示界面和行为。另一种是不带用户界面的类型,这种类型只允许我们处理来自Host应用的请求。

03.png

现在我们在工程中就可以看到刚才创建的Action扩展NoteAppExtension,它包含两个主要的文件,一个是Action.js,另一个是ActionRequestHandler.swift:

04.png

我们来看看这两个文件的作用。Action.js文件用来实现和处理浏览器中请求的逻辑,在本文的例子中,它主要实现用户在浏览器中选中文本并发送到我们的应用中。ActionRequestHandler.swift用来处理Host应用发送的请求和参数。

在实现逻辑之前我们需要设置一下扩展的属性,打开Info.plist文件将NSExtensionActivationSupportsWebURLWithMaxCount属性设置为1,该设置让扩展知道我们需要请求一个URL。

05.png

我们Action.js文件中有如下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
var 
Action = 
function
() {};
  
Action.prototype = {
     
    
run: 
function
(arguments) {
        
// Here, you can run code that modifies the document and/or prepares
        
// things to pass to your action's native code.
         
        
// We will not modify anything, but will pass the body's background
        
// style to the native code.
        
var 
selected = 
"No Text Selected"
;
        
if 
(window.getSelection) {
            
selected = window.getSelection().getRangeAt(0).toString();
        
else 
{
            
selected = document.getSelection().getRangeAt(0).toString();
        
}
        
arguments.completionFunction({
"args" 
: selected});
    
},
     
    
finalize: 
function
(arguments) {
        
// This method is run after the native code completes.
         
        
// We'll see if the native code has passed us a new background style,
        
// and set it on the body.
        
alert(arguments[
"message"
])
    
}
};
     
var 
ExtensionPreprocessingJS = 
new 
Action

Safari与Action扩展的交互就是通过Action.js文件中的run和finalize这两个方法实现的。当我们在Safari中使用Action扩展时就会调用run方法,它能让我们在该方法中操作当前Safari显示页面的DOM元素。当Action扩展处理完逻辑向Safari返回信息时会调用finalize方法,在我们的例子中,我们通过self.extensionContext!.completeRequestReturningItems(nil, completionHandler: nil)这段代码向Safari返回信息。该方法的第一个参数就是要返回的信息,它会将信息传给Action.js文件,然后通过js代码操作HTML。如果第一个参数传入nil,那就意味着不会调用Action.js文件中的finalize方法。run和finalize这两个方法的参数arguments都包含着一些信息,只不过一个是来自与HTML,一个来自ActionRequestHandler文件。

一定要记住:我们必须要实例化ExtensionPreprocessingJS这个全局变量,因为它是Safari和Action扩展之间的桥梁。

我们的ActionRequestHandler文件内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
class ActionRequestHandler: NSObject, NSExtensionRequestHandling {
  
    
var 
extensionContext: NSExtensionContext?
     
    
func beginRequestWithExtensionContext(context: NSExtensionContext!) {
        
self.extensionContext = context
        
let identifierType = NSString(format: kUTTypePropertyList, NSUTF8StringEncoding)
        
for 
(item: NSExtensionItem) 
in 
context.inputItems as [NSExtensionItem] {
            
for 
(itemProvider: NSItemProvider) 
in 
item.attachments as [NSItemProvider] {
                
if 
itemProvider.hasItemConformingToTypeIdentifier(identifierType) {
                    
itemProvider.loadItemForTypeIdentifier(identifierType, options: nil, completionHandler: {(item, error) 
in
                        
let dictionary = item as NSDictionary
                        
dispatch_async(dispatch_get_main_queue(), {
                            
self.itemLoadCompletedWithPreprocessingResults(dictionary[NSExtensionJavaScriptPreprocessingResultsKey] as NSDictionary)
                        
})
                    
})
                
}
            
}
        
}
    
}
     
    
func itemLoadCompletedWithPreprocessingResults(javaScriptPreprocessingResults: NSDictionary) {
        
if 
let text = javaScriptPreprocessingResults[
"args"
] as? String {
            
let userDefaults = NSUserDefaults(suiteName: 
"group.name"
)
            
userDefaults.setValue(text, forKey: 
"note"
)
            
userDefaults.synchronize()
            
self.doneWithResults([
"message"
"Successfully added to the note app"
])
        
}
    
}
     
    
func doneWithResults(resultsForJavaScriptFinalizeArg: NSDictionary?) {
        
if 
let resultsForJavaScriptFinalize = resultsForJavaScriptFinalizeArg {
            
let identifierType = NSString(format: kUTTypePropertyList, NSUTF8StringEncoding)
            
// Construct an NSExtensionItem of the appropriate type to return our
            
// results dictionary in.
             
            
// These will be used as the arguments to the JavaScript finalize()
            
// method.
             
            
var 
resultsDictionary = [NSExtensionJavaScriptFinalizeArgumentKey: resultsForJavaScriptFinalize]
             
            
var 
resultsProvider = NSItemProvider(item: resultsDictionary, typeIdentifier: identifierType)
             
            
var 
resultsItem = NSExtensionItem()
            
resultsItem.attachments = [resultsProvider]
             
            
// Signal that we're complete, returning our results.
            
self.extensionContext!.completeRequestReturningItems([resultsItem], completionHandler: nil)
        
else 
{
            
// We still need to signal that we're done even if we have nothing to
            
// pass back.
            
self.extensionContext!.completeRequestReturningItems(nil, completionHandler: nil)
        
}
         
        
// Don't hold on to this after we finished with it.
        
self.extensionContext = nil
    
}
}

现在我们可以运行一下我们的应用,然后打开Safari,在Action选项中开启我们的Action扩展:

06.png

然后我们就可以在Action栏中看到我们的扩展了:

07.png

我们使用Safari随便打开一个含有文字的页面,选中一段文字,然后打开Action栏,点击NoteApp扩展,此时我们的扩展就会将选中的这段文字发送给我们的应用,形成一条新的重要信息。

08.png

以上只是一个简单的Aciton扩展的例子,但我们可以由此延伸出更多有用、有创意的功能,让我们的生活更加美好。

本文例子的代码可以在这里下载:

原文地址:

转载地址:https://blog.csdn.net/hengshujiyi/article/details/39519531 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:删除SVN三种方法delSvn(windows+linux)
下一篇:不容错过的iOS 8的导航交互

发表评论

最新留言

感谢大佬
[***.8.128.20]2024年03月21日 15时42分13秒