UIActivityViewController 为 'copyToPasteboard' 操作向 UIPasteboard 添加其他类型

UIActivityViewController to add additional types to UIPasteboard for 'copyToPasteboard' action

我的应用程序的主要数据结构符合 'Codable' 协议,可以使用它来序列化其数据 to/from JSON。当用户在 UIActivityViewController 中选择 'Copy' 时,我希望能够将这些数据包含在通用粘贴板 (UIPasteboard.general) 中。

但是,我不知道该怎么做。将 JSON 添加到 activity 控制器的项目中,无论是作为数据、字符串还是字典,都没有帮助。打印粘贴板项目的类型仅显示您对属性字符串的期望:

["com.apple.uikit.attributedstring", "com.apple.rtfd", "com.apple.flat-rtfd", "public.utf8-plain-text"]

根据 UIActivity.ActivityType.copyToPasteboard 的文档:

When using this service, you can provide NSString, UIImage, NSURL, UIColor, and NSDictionary objects as data for the activity items.

所以我曾预计在 'items' 中包含字典会自动将字典项目添加到粘贴板(将字典键作为粘贴板项目类型)。但这在这种情况下似乎不起作用,即使我只使用一个简单的 [String:String] 字典。

我正在尝试的代码如下。

    func shareStuff() {
        let attrString = someThing.attrString()
        let printer = CustomPrintPageRenderer(someThing)

        var pasteboardDict: [String:Any] = [:]
        let jsonEncoder = JSONEncoder()
        jsonEncoder.outputFormatting = .prettyPrinted
        let jsonData = try? jsonEncoder.encode(someThing)
        let jsonString = String(data: jsonData!, encoding: .utf8)
        print(jsonString!)
        if jsonData != nil {
            pasteboardDict["jsonData"] = jsonData
            if jsonString != nil {
                pasteboardDict["jsonString"] = jsonString
            }
        }

        let items = [printer, attrString, pasteboardDict] as [Any]
        let activity = UIActivityViewController(activityItems: items, applicationActivities: nil)
        present(activity, animated: true)
    }

我也试过在 'items' 中包含“self”并使用 'UIActivityItemSource' 协议,但这似乎对粘贴板上的内容没有任何影响(而且我有确认 returns 字典确实被调用了):

    func activityViewController(_ activityViewController: UIActivityViewController, itemForActivityType activityType: UIActivity.ActivityType?) -> Any? {
        if activityType == .copyToPasteboard {
            return ["blah": "some stuff"]
        } else {
            return nil
        }
    }

有什么方法可以使用 UIActivityViewController 的 'Copy' activity 向粘贴板添加额外的类型吗?

或者我是否必须在 activity 视图控制器之外创建自己的单独 'Copy' 操作(并从 activity 控制器中排除 'copyToPasteboard' 以避免混淆) ?

我找到了解决方案,我的 'paste' 进程现在可以识别粘贴板上现在有 'jsonData' 和 'jsonString',以及属性字符串和纯文本。

我不得不将 'self' 作为唯一项,而不是将 'self' 添加到 'items'。然后我可以定义协议函数返回哪些项目:

    func activityViewController(_ activityViewController: UIActivityViewController, itemForActivityType activityType: UIActivity.ActivityType?) -> Any? {
        guard let recipe = recipe else { return nil }
        let attrString = someThing.attrString()
        switch activityType {
        case UIActivity.ActivityType.print:
            return SomePrintPageRenderer(someThing)
        case UIActivity.ActivityType.copyToPasteboard:
            var pasteboardDict: [String:Any] = attrString.pasteables()
            let jsonEncoder = JSONEncoder()
            jsonEncoder.outputFormatting = .prettyPrinted
            let jsonData = try? jsonEncoder.encode(someThing)
            let jsonString = String(data: jsonData!, encoding: .utf8)
            print(jsonString!)
            if jsonData != nil {
                pasteboardDict["jsonData"] = jsonData
                if jsonString != nil {
                    pasteboardDict["jsonString"] = jsonString
                }
            }
            return pasteboardDict
        default:
            return attrString
        }
    }

请注意,我还必须明确处理我仍然需要的各种普通和属性字符串粘贴板类型的包含。 (这是通过自定义 NSAttributedString 扩展完成的,函数 'pasteables()' 其中 returns 属性字符串的可粘贴版本的字典。)