Skip to content
On this page

创建Action Extention

无UI版本

之前开发了一个去水印的应用,想实现在相册注册一个Action,当在相册选择一个图片后,点击这个Action即打开App进行去水印的处理。这里需要用的Action Extention

在工程中添加一个Target,选择Action Extention:

target

点击下一步后,输入Product Name,语言选择Swift,选择有用户界面。

target

这里会生成相应的代码,包含一个Storyboard文件,一个ViewController。我们实现的目标是,当我们的Action被点击后,不出现对应的UI,直接跳到我们APP中

null

如果我们直接在viewWillAppear中,直接结束,就不会出现UI,所以我们把逻辑写在这里:

swift
 override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
       var imageFound = false
        for item in self.extensionContext!.inputItems as! [NSExtensionItem] {
            for provider in item.attachments! {
                if provider.hasItemConformingToTypeIdentifier(UTType.image.identifier) {

                    provider.loadItem(forTypeIdentifier: UTType.image.identifier, options: nil, completionHandler: { (imageURL, error) in
                            DispatchQueue.global(qos: .userInitiated).async{
                            
                            if let imageURL = imageURL as? URL {
                                //3HG5533YQ5
                                let defaults = UserDefaults(suiteName: "group.or.sofent.RemoverWaterMark")
                                do{
                                    let imageData: Data = try Data(contentsOf: imageURL)
                                    defaults?.set(imageData, forKey: imageURL.absoluteString)
                                   
                                }catch{
                                        print("Unable to load data: \(error)")
                                }
                               openMainApp(imageURL)
                            }
                            
                        }
                    })
                    
                    imageFound = true
                    break
                }
            }
            
            if (imageFound) {
                // We only handle one image, so stop looking for more.
                break
            }
        }
       
            done()
        
    }

有UI版本

主APP又加了一个功能给图片智能抠图。所以在选择这个Action的时候,需要让用户选择是使用哪个功能。Xcode生成的代码是基于UIKit的,我们想使用SwiftUI来写

选择我们把Info.plist 中把NSExtensionMainStoryboard删除,然后添加NSExtensionPrincipalClass。这样我们就不再依赖Storyboard,可以使用代码来遍写UI。

xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>NSExtension</key>
	<dict>
		<key>NSExtensionAttributes</key>
		<dict>
			<key>NSExtensionActivationRule</key>
			<string>TRUEPREDICATE</string>
			<key>NSExtensionServiceAllowsFinderPreviewItem</key>
			<true/>
			<key>NSExtensionServiceAllowsTouchBarItem</key>
			<true/>
			<key>NSExtensionServiceFinderPreviewIconName</key>
			<string>NSActionTemplate</string>
			<key>NSExtensionServiceTouchBarBezelColorName</key>
			<string>TouchBarBezel</string>
			<key>NSExtensionServiceTouchBarIconName</key>
			<string>NSActionTemplate</string>
		</dict>
        <key>NSExtensionPrincipalClass</key>
        <string>ActionViewController</string>
        <key>NSExtensionMainStoryboard<key>
        <string>MainInterface</string>
		<key>NSExtensionPointIdentifier</key>
		<string>com.apple.ui-services</string>
	</dict>
</dict>
</plist>

由于入口是一个UIViewController,所以我们需要想用SwiftUI来开发的话,需要进行进行集成,可以通过UIHostingController来实现

swift
 override func viewDidLoad() {
        super.viewDidLoad()
        
        let child = UIHostingController(rootView: ContentView{ str in
                self.openContainerApp(self.imageURLStr,type: str)
                self.done()
        })
        child.view.translatesAutoresizingMaskIntoConstraints = false
        let bounds = self.view.bounds
        child.view.frame = CGRect(origin: CGPoint(x: 0, y: bounds.height/3*2), size: CGSize(width: bounds.width, height: bounds.height/3))
        // First, add the view of the child to the view of the parent
        self.view.addSubview(child.view)
        // Then, add the child to the parent
        self.addChild(child)
        // For example, look for an image and place it into an image view.
        // Replace this with something appropriate for the type[s] your extension supports.
        
    }