Swift闭包强烈捕获引用类型。

DispatchGroup是引用类型。

我的问题与以下代码有关:

func getUsername(onDone: @escaping (_ possUsername: String?) -> ())
{
    //Post request for username that calls onDone(retrievedUsername)...
}

func getBirthdate(using username: String?, onDone: @escaping (_ possBday: String?) -> ())
{
    //Post request for token that calls onDone(retrievedToken)...
}

func asyncTasksInOrder(onDone: @escaping (_ resultBDay: String?) -> ())
{
    let thread = DispatchQueue(label: "my thread", qos: .userInteractive, attributes: [],
                               autoreleaseFrequency: .workItem, target: nil)
    thread.async { [weak self, onDone] in
        guard let self = self else {
            onDone(nil)
            return
        }
        let dg = DispatchGroup()        //This is a reference type
        var retrievedUsername: String?
        var retrievedBday: String?

        //Get username async first
        dg.enter()
        self.getUsername(onDone: {[weak dg](possUsername) in
            retrievedUsername = possUsername
            dg?.leave() //DG is weak here
        })
        dg.wait()

        //Now that we've waited for the username, get bday async now
        dg.enter()
        self.getBirthdate(using: retrievedUsername, onDone: {[weak dg](possBday) in
            retrievedBday = possBday
            dg?.leave() //DG is also weak here
        })
        dg.wait()

        //We've waited for everything, so now call the return callback
        onDone(retrievedBday)
    }
}

因此asyncTasksInOrder(onDone:)内部的两个闭包分别捕获了我的DispatchGroup dg
  • 甚至有必要捕获我的调度组吗?
  • 如果我不捕获它,我怎么会知道我有一个保留周期?
  • 如果在回调执行之一中调度组消失,该怎么办?它在等待时甚至会蒸发吗?
  • 经常像这样实例化Dispatch 队列,是否不必要地昂贵(不考虑.userInteractive)?我之所以问这个特定问题,是因为在Android中扩展线程非常昂贵(如此昂贵,以至于JetBrains为Kotlin协程投入了大量资源)。
  • dg.notify(...)如何参与所有这些工作?当dg.wait()做同样的事情时,为什么还要有一个notify方法呢?

  • 我觉得我对GCD的理解不是一帆风顺的,所以我要求树立信心。如果有什么要批评的话,也请批评。非常感谢您的帮助。

    最佳答案

    1)不,调度组是隐式捕获的。您甚至不需要捕获self中的async,因为GCD闭包不会引起保留周期。

    2)没有保留周期。

    3)实际上,您滥用DispatchGroup来强制异步任务变得同步。

    4)不,GCD非常轻巧。

    5)DispatchGroup的主要目的是在完成所有异步任务(例如,在重复循环中)时,不管顺序如何,将其转换为notify

    更好的解决方案是嵌套异步任务。仅需完成两项任务,厄运金字塔就可以管理了。

    func asyncTasksInOrder(onDone: @escaping (String?) -> Void)
    {
        let thread = DispatchQueue(label: "my thread", qos: .userInteractive, autoreleaseFrequency: .workItem)
        thread.async {
    
            //Get username async first
            self.getUsername { [weak self] possUsername in
                guard let self = self else { onDone(nil); return }
    
                //Now get bday async
                self.getBirthdate(using: possUsername) { possBday in
    
                   //Now call the return callback
                    onDone(possBday)
                }
            }
        }
    }
    

    07-28 02:36
    查看更多