swift 在循环中,调用一个具有完成处理程序的函数,对结果进行排序

ykejflvf  于 2023-05-16  发布在  Swift
关注(0)|答案(2)|浏览(166)

我有以下问题,也许有一个解决方案。我需要从同步代码在一个循环中调用一个给定的函数和一个完成处理程序。问题是函数调用可能没有按顺序完成,我需要找到一种方法来知道返回值的顺序。

func findNextWord(completionHandler: @escaping (String) -> Void) // Given

class A {
    var words = [String]()

    func retrieveAllWords() {
        for _ in 0...20 {
            findNextWord { [weak self] word in 
            self.words.append(word)  // I want to be able to get the correct ordering in my array
        }
    }
}

最好的办法是什么?先谢谢你了。

实验

注意:我测试了一些东西,我注意到闭包显示变量a及其在函数被调用时的值。也许这和那有关系。

import Foundation

class A {
    
    let queue = DispatchQueue(label: "test")
    
    var a = 0
    
    func doInLoop() {
        for _ in 0...5 {
            doSomething()
        }
    }
    
    func doSomething() {
        a += 1
        let a_not_self = a
        print("outside a: \(a_not_self)")
        orderPizza { [weak self] in
            print("inside a: \(a_not_self)")
            print("inside a (but self): \(self?.a)\n")
        }
    }
    
    func orderPizza(completionHandler : @escaping () -> Void) {
        queue.async {
            sleep(5)
            completionHandler()
        }
    }
}

var a = A()
a.doInLoop()

打印:

outside a: 1
outside a: 2
outside a: 3
outside a: 4
outside a: 5
outside a: 6
inside a: 1
inside a (but self): Optional(6)

inside a: 2
inside a (but self): Optional(6)

inside a: 3
inside a (but self): Optional(6)

inside a: 4
inside a (but self): Optional(6)

inside a: 5
inside a (but self): Optional(6)

inside a: 6
inside a (but self): Optional(6)
4ioopgfo

4ioopgfo1#

你可以使用字典代替数组(或者两者都用)

class A {
    var words = [Int: String]()

    func retrieveAllWords() {
        for index in 0...20 {
            findNextWord { [weak self] word in 
            self.words[index] = word
        }
    }
}
z4bn682m

z4bn682m2#

最好的办法是什么?
最好的方法是async/await
您不必关心weak self或调用完成处理程序。只需要退出方法或返回一些东西。循环按顺序执行。

class A {
    func doInLoop() async  {
        for i in 1...5 {
            print("preparation \(i)")
            await doSomething(i)
        }
        print("finished")
    }
    
    func doSomething(_ index: Int) async {
       let result = await orderPizza(index)
        print("completion: " + result)
    }
    
    func orderPizza(_ index: Int) async -> String {
        try! await Task.sleep(for: .seconds(2))
        return "Pizza \(index)"
    }
}

Task {
    let a = A()
    await a.doInLoop()
}

(旧的)GCD方法是使用DispatchGroup

相关问题