ios - 使用闭包时如何防止时序问题?

标签 ios swift closures dispatch-queue

我正在尝试求出从不同的转义闭包返回的数字之和。在主线程中返回的总和。

import Foundation

var randomTime: Int {
  return Int.random(in: 0...1000)
}

func first(completion: @escaping (Int) -> Void) {
  DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(randomTime)) {
    completion(1)
  }
}

func second(completion: @escaping (Int) -> Void) {
  DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(randomTime)) {
    completion(2)
  }
}

func third(completion: @escaping (Int) -> Void) {
  DispatchQueue(label: "anotherThread").async {
    completion(3)
  }
}

func fourth(completion: @escaping (Int) -> Void) {
  DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(randomTime)) {
    completion(4)
}
}

最佳答案

如果我把你的问题说清楚了,你想对数字求和,但它们的值会在不同的时间出现,具体取决于服务器响应或某种延迟。如果是这种情况,那么您必须使用 DispatchGroup

这是一个辅助函数,它调用你的方法 first(completion: @escaping (Int) -> Void)..... fourth(completion: @escaping (Int ) -> Void) 并仅在收到最后一个值时通知主队列。我在代码上添加了一些注释以帮助理解。如果有什么不清楚的地方,请告诉我。


    func computeOutPutAfterReceivingAllValues(completion: @escaping(_ sum: Int) -> Void) {
        // Make a dispatch group which will notify main queue after making sure that all requests have been proceed.
        let computeGroup = DispatchGroup()
        var allNumbers: [Int] = []
        computeGroup.enter()
        first { (firstNumber) in
            allNumbers.append(firstNumber)
            self.second(completion: { (secondNumber) in
                allNumbers.append(secondNumber)
                self.third(completion: { (thirdNumber) in
                    allNumbers.append(thirdNumber)
                    self.fourth(completion: { (fourthNumber) in
                        allNumbers.append(fourthNumber)
                         // IMPORTANT: Leave a group after the last call.
                        computeGroup.leave()
                    })
                })
            })

        }


        // Notify Main queue and sum all your numbers
        computeGroup.notify(queue: .main) {
            /// Sum all your numbers in main queue
            let sum = allNumbers.reduce(0, +)
            completion(sum)
        }
    }

用法: 您可以在 didLoad View 中对此进行测试。

 override func viewDidLoad() {
        super.viewDidLoad()
        computeOutPutAfterReceivingAllValues { (sum) in
            print("Here is the sum of all numbers: \(sum)")
        }
    }

// Output on console
    Here is the sum of all numbers: 10


关于ios - 使用闭包时如何防止时序问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57983761/

相关文章:

ios - 无需标注即可转换 MKAnnotationView

swift - 未能实现符合类型的协议(protocol)扩展

Swift 闭包更改捕获的变量

iphone - iOS 中的测试驱动开发......是否采用 TDD

ios - 如何在iOS WKWebView应用程序中下载.vcf文件并将其直接保存到iPhone的联系人中?

ios - 在内存不足的 iOS 中播放 Motion JPG 流

ios - 新的高分弹出窗口

快速图像选择器获取几张图片

swift - 无法访问闭包之外的自定义

java - 无法调用匿名类方法