Создайте UID-документ на лету в UIActivityItemProvider - PullRequest
0 голосов
/ 16 апреля 2019

Я использую Core Data для хранения данных моего пользователя.Я хочу предложить кнопку «Поделиться» в пользовательском интерфейсе для экспорта данных в любое место.Я сделал класс, соответствующий UIActivityItemSource.Он успешен, когда просто возвращает объект данных из activityViewController:itemForActivityType, но файл имеет системное имя файла.Поэтому сейчас я пытаюсь сгенерировать UIDocument на лету, сохранить его в файловой системе и вернуть URL (UIDocument.fileURL) в контроллер представления активности.Проблема в UIDocument.save асинхронная, но я не могу вернуться с activityViewController:itemForActivityType, пока файл не будет сохранен.Мой последний код выглядит так:

Класс init:

let saveQueue = DispatchQueue(label: "saveQueue")
let saveSemaphore = DispatchSemaphore(value: 0)

...

func activityViewController(_ activityViewController: UIActivityViewController, itemForActivityType activityType: UIActivity.ActivityType?) -> Any? {
    var success = false
    self.saveQueue.async {
        self.document.save(to: self.document.fileURL,
                           for: .forOverwriting) {(didSucceed) in
            success = didSucceed
            self.saveSemaphore.signal()
        }
    }
    saveSemaphore.wait()
    return success ? document.fileURL : nil
}

Поведение - асинхронный код запускается, но завершается сохранениефункция никогда не вызывается.Что я сделал (и не сделал)?


Мое окончательное решение, с помощью Кейси, было переопределить UIDocument.save.

override func save(to url: URL, for saveOperation: UIDocument.SaveOperation, completionHandler: ((Bool) -> Void)? = nil) {
    do {
        let contents = try self.contents(forType: GlobalConst.exportType) as! Data
        try contents.write(to: url, options: [.atomicWrite])
        completionHandler?(true)
    } catch {
        print("write error: \(error)")
        completionHandler?(false)
    }
}

Мне еще предстоит понять, почему сохранение суперкласса было проблемой, но я могу позволитьэто скользит.

1 Ответ

1 голос
/ 16 апреля 2019

Чтобы заставить его работать, мне пришлось создать подкласс UIDocument и переопределить func save(to:for:completionHandler:)

class MyDocument: UIDocument {

    var body: String = "Hello world, this is example content!"

    override func save(to url: URL, for saveOperation: UIDocument.SaveOperation, completionHandler: ((Bool) -> Void)? = nil) {
        do {
            try self.body.write(toFile: url.path, atomically: true, encoding: .utf8)
            completionHandler?(true)
        } catch {
            print("write error: \(error)")
            completionHandler?(false)
        }
    }
}

Ваш код остался прежним, просто убедитесь, что self.document имеет тип MyDocument (или любой другой подкласс, который у вас, вероятно, уже есть).

let document = MyDocument(fileURL: URL(fileURLWithPath: NSHomeDirectory() + "/Documents/output.txt"))
...