UIActivityViewController «Сохранить в файлы» сохраняет несколько файлов, когда требуется только 1 файл - PullRequest
0 голосов
/ 21 апреля 2020

Мое приложение может предоставлять различные типы UIActivityItem (текст, данные, форматированный текст, средство печати страниц печати и т. Д. c) для совместного использования в различных целях, включая печать, копирование / вставку и сохранение в виде файл. Для целей копирования / вставки необходимо включить обычный текст, атрибутивную строку, данные (JSON Data) и JSON string).

Однако, поскольку предусмотрено несколько типов данных, UIActivityViewController's " Параметр «Сохранить в файлы» приводит к сохранению нескольких файлов - по одному для каждого из типов элементов, которые могут быть сохранены в виде файла.

Если я уменьшу его до одного 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

.. .и файл создается для каждого из них, если я просто передам элемент для этого типа данных.

1 Ответ

0 голосов
/ 23 апреля 2020

Ну, я обнаружил, что решение было двояким ...

Прямой ответ на вопрос (но не идеальное поведение):

В каждом из switch случаев (и if в случае default) мне нужно было проверить, что activityType соответствует placeholderItem. Если это не подходящее совпадение, верните (пустой) placeholderItem как есть (за исключением того, что в случае «Сохранить в файлы» даже пустой заполнитель средства отображения страницы печати приводил к записи файла! Так что вместо возврата заполнителя) верните пустой массив).

Это сработало, и в результате один файл был записан в папку по выбору пользователя, что отвечает на исходный вопрос. Пользователь даже получает возможность указать имя для файла. Но имя по умолчанию совсем не годится - только тип данных (например, «текст» или «данные», в зависимости от того, что было сохранено в файл).

Решение, обеспечивающее большую гибкость : Создайте пользовательский UIActivity, который будет записывать файл в местоположение, выбранное пользователем, с помощью UIDocumentPickerViewController. Например, у действия может быть заголовок, такой как «Экспорт в»).

Это оказалось намного более гибким, и я позволю себе использовать имя файла по умолчанию (и расширение!), Которое имело гораздо больший смысл на основе передаваемых данных. У меня также есть возможность добавить дополнительные улучшения в поведение позже (например, я мог бы использовать предупреждение, чтобы пользователь мог выбрать между несколькими различными форматами файлов (для использования для различных целей).

Это не заменяет действие «Сохранить в файлы», поэтому я в итоге выбрал оба из них, и мне все еще нужно было исправить поведение действия «Сохранить в файлы», как описано выше.

Это оставляет мне действие «Экспорт» и «Сохранить», которые работают аналогично, но одно более гибкое и интуитивно понятное, чем другое, и я могу заставить их использовать разные форматы файлов по умолчанию.

Мой новый код (для default части внешнего switch) ниже ...

        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
        }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...