【问题标题】:Running a block after several calls to loadFileRepresentation have finished在对 loadFileRepresentation 的多次调用完成后运行一个块
【发布时间】:2019-09-17 04:33:08
【问题描述】:

我正在使用 NSItemProvider 方法 loadFileRepresentation(forTypeIdentifier: completionHandler:)。该方法将一些数据异步写入一个临时文件,并立即返回一个表示此写入进度的 Progress 对象。它还接受一个块,当临时文件已写入并准备好供您使用时将调用该块。 (如果准备文件时出错,也会调用该块。)

我将连续多次调用此方法,并希望在我的 UI 中显示“请稍候”消息,直到我的每个块都完成。如何以线程安全的方式执行此操作?

【问题讨论】:

    标签: ios thread-safety


    【解决方案1】:

    显示带有“请稍候”消息的对话框。然后遍历扩展上下文的inputItems 两次:一次只是为了计算我们想要处理的文件数,然后再一次是为了实际处理它们。当处理的文件数量等于我们预期的数量时,我们调用另一个实例方法来隐藏对话框并将控制权返回给宿主应用程序。

    为了线程安全,处理的数字的递增以及处理的数字与预期数字之间的比较是在序列号DispatchQueue 上完成的。这确保了即使传递给loadFileRepresentation 的块的多个副本同时运行,扩展仍然能够正确识别何时处理完文件。

    import UIKit
    
    class ShareViewController: UIViewController {
        override func viewWillAppear(_ animated: Bool) {
            super.viewWillAppear(animated)
    
            guard let items = extensionContext?.inputItems as? [NSExtensionItem] else {
                return
            }
    
            // Display a "please wait" message while we copy the files.
    
            let alertVC = UIAlertController(title: nil,
                                            message: "Processing files…",
                                            preferredStyle: .alert)
            present(alertVC, animated: false, completion: nil)
    
            // Iterate through the files once, incrementing "numberExpected" each
            // time we see a file we're interested in.
    
            var numberExpected: Int = 0
    
            for item in items {
                guard let attachments = item.attachments else {
                    continue
                }
    
                for attachment in attachments {
                    if attachmentShouldBeProcessed(attachment) {
                        numberExpected += 1
                    }
                }
            }
    
            // Iterate through the files again, actually processing them this time.
            // After each file is done--whether it succeeded or not--we increment
            // "numberProcessed" and compare it to "numberExpected". (It's very
            // important that this be done in a thread-safe way, which we accomplish
            // here by doing the comparison within a block that is run on a serial
            // DispatchQueue.) If they're equal, call the finish() method to close
            // the progress dialog and return control of the UI to the host app.
    
            var numberProcessed: Int = 0
            let queue = DispatchQueue(label: "com.myapp.file-processing-queue")
    
            for item in items {
                guard let attachments = item.attachments else {
                    continue
                }
    
                for attachment in attachments {
                    guard attachmentShouldBeProcessed(attachment) else {
                        continue
                    }
                    attachment.loadFileRepresentation(forTypeIdentifier: "public.png") { url, error in
    
                        // ...your business logic here...
    
                        queue.sync {
                            numberProcessed += 1
                            if numberProcessed == numberExpected {
                                DispatchQueue.main.async { [weak self] in
                                    self?.finish()
                                }
                            }
                        }
                    }
                }
            }
        }
    
        func finish() {
            // Dismiss the "processing items" dialog.
            dismiss(animated: false, completion: nil)
    
            // Inform the host app that we're done so it can un-block its UI.
            extensionContext!.completeRequest(returningItems: [], completionHandler: nil)
        }
    
        func attachmentShouldBeProcessed(_ attachment: NSItemProvider) -> Bool {
            // ...your business logic here...
            return true
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2013-01-03
      • 2018-11-05
      • 1970-01-01
      • 1970-01-01
      • 2016-12-26
      • 2016-12-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多