【问题标题】:UIActivityViewController "Save to Files" saves multiple files when only 1 file is requiredUIActivityViewController“保存到文件”只需要1个文件时保存多个文件
【发布时间】:2020-04-21 05:23:58
【问题描述】:

我的应用能够提供多种 UIActivityItem 类型(文本、数据、富文本、打印页面渲染器等)以用于各种用途的共享,包括打印、复制/粘贴和另存为文件。出于复制/粘贴的目的,它需要包含纯文本、属性字符串、数据(JSON 数据)和 JSON 字符串)。

但是,由于提供了多种数据类型,因此 UIActivityViewController 的“保存到文件”选项会导致保存多个文件 - 一个用于可以保存为文件的每种项目类型。

如果我将它减少到只有一个 UIActivityItem,那么复制/粘贴功能会严重减少,因此它不能适用于它应该使用的所有各种不同的粘贴板类型(例如,我的应用程序的自定义 JSON 数据格式和纯文本和属性字符串)。

所以我试图使用 UIActivityItemProvider 子类来解决这个问题,但我仍然无法弄清楚如何只保存一个文件,而不是多个文件(每个项目类型一个)。这甚至可能吗?

我的 UIActivityItemProvider 子类的相关部分如下。

(请注意,我为此使用了单个子类的多个实例,但使用不同的子类也会出现同样的问题。)

class RatsActivityItemProvider: UIActivityItemProvider {

    var rats: [Rat]

    init(placeholderItem: Any, rats: [Rat]) {
        RatsActivityItemProvider.selectedOption = nil
        self.rats = rats
        super.init(placeholderItem: placeholderItem)
    }

    class func allProviders(forRats rats: [Rat]) -> [RatsActivityItemProvider] {
        var providers: [RatsActivityItemProvider] = []
        providers.append(RatsActivityItemProvider(placeholderItem: NSAttributedString(), rats: rats))
        providers.append(RatsActivityItemProvider(placeholderItem: RatPrintPageRenderer(), rats: rats))
        providers.append(RatsActivityItemProvider(placeholderItem: [:] as [String:Any], rats: rats))
        providers.append(RatsActivityItemProvider(placeholderItem: Data(), rats: rats))
        return providers
    }

    override var item: Any {
        print("\(activityType!.rawValue as Any) - \(type(of: placeholderItem!))")
        switch activityType {
        case UIActivity.ActivityType.print:
            return RatPrintPageRenderer(rats)
        case UIActivity.ActivityType.copyToPasteboard:
            var pasteboardDict: [String:Any] = attrString.pasteables()
            //  (Add custom types to dictionary here)
            return pasteboardDict
        default:
            //  "Save To Files" activity is not available in UIActivity.ActivityType so check the raw value instead
            if activityType?.rawValue.contains("com.apple.CloudDocsUI.AddToiCloudDrive") ?? false {
                //
                //  HOW TO HAVE ONLY ONE OF THE PROVIDERS RETURN A VALUE HERE???
                //
            }
        }
    }

}

当我运行它并选择“保存到文件”时,我得到以下输出(来自每个提供者的一行):

com.apple.CloudDocsUI.AddToiCloudDrive - NSConcreteAttributedString
com.apple.CloudDocsUI.AddToiCloudDrive - RecipePrintPageRenderer
com.apple.CloudDocsUI.AddToiCloudDrive - __EmptyDictionarySingleton
com.apple.CloudDocsUI.AddToiCloudDrive - _NSZeroData

...如果我简单地传回该数据类型的项目,则会为其中的每一个创建一个文件。

【问题讨论】:

    标签: swift file save uiactivityviewcontroller uiactivityitemprovider


    【解决方案1】:

    嗯,我发现解决方案有两个...

    直接回答问题(但不是理想的行为):

    在每个switch 案例中(以及default 案例中的if),我需要检查activityType 是否与placeholderItem 匹配。如果它不是一个合适的匹配项,则按原样返回(空)placeholderItem(除了在“保存到文件”的情况下,即使是空的打印页面渲染器占位符也会导致文件被写入!所以而不是返回占位符在那里,返回一个空数组)。

    这有效,并导致将单个文件写入用户选择的位置,从而回答了原始问题。用户甚至有机会为文件提供名称。但是默认名称一点都不好——只是数据类型(例如,“文本”或“数据”,取决于保存到文件中的内容)。

    提供更多灵活性的解决方案: 创建一个自定义UIActivity,它将文件写入用户使用UIDocumentPickerViewController 选择的位置。例如,活动的标题可以是“导出到”)。

    事实证明这更加灵活,让我根据传入的数据使用更有意义的默认文件名(和扩展名!)。它还有可能让我进一步添加稍后改进行为(例如,我可能能够使用警报让用户在几种不同的文件格式之间进行选择(用于不同目的)。

    这不会取代“保存到文件”操作,所以我最终得到了它们,并且仍然需要修复我的“保存到文件”操作的行为,如上所述。

    它给我留下了“导出”和“保存”两个操作,它们的工作方式相似,但一个比另一个更灵活和直观,我可以让它们默认使用不同的文件格式。

    我的新代码(外部switchdefault 部分)如下...

            default:
                if activityType?.rawValue == "com.stuff.thing.activity.export" {
                    if placeholderItem is [Rat] {
                        return rats
                    } else {
                       return placeholderItem!
                   }
                } else if activityType?.rawValue == "com.apple.CloudDocsUI.AddToiCloudDrive" {
                    if placeholderItem is Data {
                        return attrString
                    } else {
                        //  Don't return the placeholder item here!  Some (eg print page renderer) can result in a file being written!
                        return [] as [Any]
                    }
                }
    
                return attrString
            }
    

    【讨论】:

      猜你喜欢
      • 2012-04-18
      • 1970-01-01
      • 2014-12-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多