Appearance
创建Action Extention
无UI版本
之前开发了一个去水印的应用,想实现在相册注册一个Action,当在相册选择一个图片后,点击这个Action即打开App进行去水印的处理。这里需要用的Action Extention。
在工程中添加一个Target,选择Action Extention:

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

这里会生成相应的代码,包含一个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.
}