在UIActivityItemProvider

时间:2019-04-15 21:42:53

标签: ios semaphore dispatch-async uidocument

我正在使用Core Data来存储用户的数据。我想在用户界面中提供一个“共享”按钮以将数据导出到他们希望的任何位置。我做了一个符合UIActivityItemSource的课程。仅从activityViewController:itemForActivityType返回一个Data对象,但是该文件具有系统提供的文件名,则表示成功。因此,我现在尝试立即生成一个UIDocument,将其保存到文件系统中,并将URLUIDocument.fileURL)返回到活动视图控制器。问题是UIDocument.save是异步的,但是在保存文件之前我无法从activityViewController:itemForActivityType返回。我的最新代码如下:

类的初始化:

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
}

该行为是异步代码启动,但从未调用保存的完成功能。我做错了什么?


在Casey的帮助下,我最终的解决方案是覆盖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 个答案:

答案 0 :(得分:1)

为了使其正常工作,我必须创建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"))