swift DispatchGroup在调用所有休假之前通知

ctzwtxfj  于 2022-12-21  发布在  Swift
关注(0)|答案(1)|浏览(112)

我有一个运行多个类的iOS应用程序(每个类在一个单独的线程中),我希望在所有类完成运行时收到通知。
所以我有一个BaseClass:

class BaseClass {
    var completeState: CompleteState
    
    init(completeState: CompleteState) {
        self.completeState = completeState
        self.completeState.dispatch.enter()
    }
    
    func start() { }
}

这是一个完整状态类:

class CompleteState {
    let userId:String
    let dispatch = DispatchGroup()
    
    init(userId:String) {
        self.userId = userId
        dispatch.notify(queue: DispatchQueue.main) {
            print("Finish load all data")
        }
    }
}

我有多个从BaseClass继承的类,它们都是这样的形式:

class ExampleClass1: BaseClass {
    override func start() {
        DispatchQueue.global().async {
            print("ExampleClass1 - Start running")

            //DOING SOME CALCULATIONS
            
            print("ExampleClass1 - Finish running")
            self.completeState.dispatch.leave()
        }
    }
}

这是运行所有这些的代码:

public class RunAll {
    let completeState: CompleteState
    let classArray: [BaseClass]
    
    public init(userId: String) {
        self.completeState = CompleteState(userId: userId)
        classArray = [ExampleClass1(completeState: completeState),
                          ExampleClass2(completeState: completeState),
                          ExampleClass3(completeState: completeState),
                          ExampleClass4(completeState: completeState),
                          ExampleClass5(completeState: completeState),
                          ExampleClass6(completeState: completeState),
                          ExampleClass7(completeState: completeState),
                          ExampleClass8(completeState: completeState),
                          ExampleClass9(completeState: completeState)]

        startClasses()
    }
    
    private func startClasses() {
        for foo in classArray {
            foo.start()
        }
    }
}

问题是,在所有类完成工作之前,我得到了dispatch.notify的调用,你知道问题是什么吗?

jjhzyzn0

jjhzyzn01#

notifydocumentation声明:
此函数计划在与调度组关联的所有块均已完成时将通知块提交至指定队列。如果组为空(没有块对象与调度组关联),则通知块对象将立即提交。提交通知块后,组为空。
您正在CompleteStateinit中调用dispatch.notify()。在您调用notify时,调度组为空,因为您尚未创建一个名为startBaseClass子类,调度组是在该子类中输入的。
因为您在调度组为空时调用notify,所以会立即提交块。
也许值得研究一下OperationQueue,但是如果您想使用现有的OperationQueue,可以将notifyinit中分离出来:

lass CompleteState {
    let userId:String
    let dispatch = DispatchGroup()
    
    init(userId:String) {
        self.userId = userId
    }
    
    func registerCompletionBlock(handler: @escaping () -> Void) {
        self.dispatch.notify(queue: DispatchQueue.main, execute: handler)
    }
}

然后,在调用startClasses之后提供完成块

public init(userId: String) {
        self.completeState = CompleteState(userId: userId)
        classArray = [ExampleClass1(completeState: completeState),
                          ExampleClass2(completeState: completeState),
                          ExampleClass3(completeState: completeState),
                          ExampleClass4(completeState: completeState),
                          ExampleClass5(completeState: completeState),
                          ExampleClass6(completeState: completeState),
                          ExampleClass7(completeState: completeState),
                          ExampleClass8(completeState: completeState),
                          ExampleClass9(completeState: completeState)]

        startClasses()
        self.completeState.registerCompletionBlockHandler {
            print("Finish load all data")
        }
    }

相关问题