gpt4 book ai didi

ios - 共享扩展以打开包含应用程序

转载 作者:IT王子 更新时间:2023-10-29 08:05:12 25 4
gpt4 key购买 nike

我想为我的应用创建一个 Android 风格的分享功能。我创建了一个共享扩展,当您在库存照片应用程序中选择图片并按下共享时,它会被调用。现在我希望将这些图片发送到主应用程序并在那里进行处理。我现在的问题是:

  1. 在共享扩展窗口上按下按钮后,iOS 能否打开我的应用程序?
  2. 如何在我的主应用程序中获取图片文件?

最佳答案

Swift 4+(在 iOS 13 上测试)

@objc应该加在openURL的声明中,即

@objc func openURL(_ url: URL) -> Bool {
// Code below.
}

没有它,人们会看到这个编译器错误:

Argument of '#selector' refers to instance method 'openURL' that is not exposed to Objective-C

Swift 3.1 中的工作解决方案(在 iOS10 中测试):

您需要创建自己的 URL Scheme,然后将此函数添加到您的 ViewController 并使用 openURL("myScheme://myIdentifier") 调用它

//  Function must be named exactly like this so a selector can be found by the compiler!
// Anyway - it's another selector in another instance that would be "performed" instead.
func openURL(_ url: URL) -> Bool {
var responder: UIResponder? = self
while responder != nil {
if let application = responder as? UIApplication {
return application.perform(#selector(openURL(_:)), with: url) != nil
}
responder = responder?.next
}
return false
}

编辑:说明说明:openURL 是 UIApplication 的一种方法 - 因为您的 ShareExtension 不是从 UIApplication 派生的,所以我添加了自己的 openURL ,其定义与 UIApplication 中的定义相同,以使编译器满意(所以可以找到#selector(openURL(_:))。

然后我遍历响应器,直到找到一个真正派生自 UIApplication 的响应器,然后在其上调用 openURL

更多精简示例代码将 ShareExtension 中的文件复制到本地目录,序列化文件名并在另一个应用程序上调用 openURL:

//
// ShareViewController.swift
//

import UIKit
import Social
import MobileCoreServices

class ShareViewController: UIViewController {

var docPath = ""

override func viewDidLoad() {
super.viewDidLoad()

let containerURL = FileManager().containerURL(forSecurityApplicationGroupIdentifier: "group.com.my-domain")!
docPath = "\(containerURL.path)/share"

// Create directory if not exists
do {
try FileManager.default.createDirectory(atPath: docPath, withIntermediateDirectories: true, attributes: nil)
} catch let error as NSError {
print("Could not create the directory \(error)")
} catch {
fatalError()
}

// removing previous stored files
let files = try! FileManager.default.contentsOfDirectory(atPath: docPath)
for file in files {
try? FileManager.default.removeItem(at: URL(fileURLWithPath: "\(docPath)/\(file)"))
}
}

override func viewDidAppear(_ animated: Bool) {

let alertView = UIAlertController(title: "Export", message: " ", preferredStyle: .alert)

self.present(alertView, animated: true, completion: {

let group = DispatchGroup()

NSLog("inputItems: \(self.extensionContext!.inputItems.count)")

for item: Any in self.extensionContext!.inputItems {

let inputItem = item as! NSExtensionItem

for provider: Any in inputItem.attachments! {

let itemProvider = provider as! NSItemProvider
group.enter()
itemProvider.loadItem(forTypeIdentifier: kUTTypeData as String, options: nil) { data, error in
if error == nil {
// Note: "data" may be another type (e.g. Data or UIImage). Casting to URL may fail. Better use switch-statement for other types.
// "screenshot-tool" from iOS11 will give you an UIImage here
let url = data as! URL
let path = "\(self.docPath)/\(url.pathComponents.last ?? "")"
print(">>> sharepath: \(String(describing: url.path))")

try? FileManager.default.copyItem(at: url, to: URL(fileURLWithPath: path))

} else {
NSLog("\(error)")
}
group.leave()
}
}
}

group.notify(queue: DispatchQueue.main) {
NSLog("done")

let files = try! FileManager.default.contentsOfDirectory(atPath: self.docPath)

NSLog("directory: \(files)")

// Serialize filenames, call openURL:
do {
let jsonData : Data = try JSONSerialization.data(
withJSONObject: [
"action" : "incoming-files"
],
options: JSONSerialization.WritingOptions.init(rawValue: 0))
let jsonString = (NSString(data: jsonData, encoding: String.Encoding.utf8.rawValue)! as String).addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
let result = self.openURL(URL(string: "myapp://com.myapp.share?\(jsonString!)")!)
} catch {
alertView.message = "Error: \(error.localizedDescription)"
}
self.dismiss(animated: false) {
self.extensionContext!.completeRequest(returningItems: [], completionHandler: nil)
}
}
})
}

// Function must be named exactly like this so a selector can be found by the compiler!
// Anyway - it's another selector in another instance that would be "performed" instead.
@objc func openURL(_ url: URL) -> Bool {
var responder: UIResponder? = self
while responder != nil {
if let application = responder as? UIApplication {
return application.perform(#selector(openURL(_:)), with: url) != nil
}
responder = responder?.next
}
return false
}
}

关于ios - 共享扩展以打开包含应用程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27506413/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com