Asynchronous 在DispatchQueue.main.async Swift 3中转义闭包设置视图

Asynchronous 在DispatchQueue.main.async Swift 3中转义闭包设置视图,asynchronous,swift3,callback,closures,dispatch,Asynchronous,Swift3,Callback,Closures,Dispatch,我正在处理一些异步函数并尝试更新视图。简而言之,我有一个带有异步函数的函数1,该函数将返回一个字符串以传递给函数2。我正在主线程上更新这两个函数中的视图。这一切都是可行的,但我需要了解这是否是正确的方式 class A { var varA = "" var varB = "" func f1 (_ completion: @escaping (String) -> void ){ some asynchronous call ... { in

我正在处理一些异步函数并尝试更新视图。简而言之,我有一个带有异步函数的函数1,该函数将返回一个字符串以传递给函数2。我正在主线程上更新这两个函数中的视图。这一切都是可行的,但我需要了解这是否是正确的方式

class A {
    var varA = ""
    var varB = ""

    func f1 (_ completion: @escaping (String) -> void ){

        some asynchronous call ... { in
            ... 
            DispatchQueue.main.async {
                self.varA = "something"
                sef.labelA.text = self.varA
                completion(self.varA)
            }
        }
    }

    func f2 (_ string: String){

        another asynchronous call ... { in
            ... 
            DispatchQueue.main.async {
                self.varB = string
                sef.labelB.text = self.varB

            }
        }
    }

    // funcation call
    f1(completion: f2)
}
有三个问题,1)在存在等待异步回调的情况下,运行依赖函数的正确方法是什么

2) 更新视图是否需要DispatchQueue.main.async


3) 在另一个异步回调中调用async func可以吗?如果您在某些转义函数中更新视图,在某些情况下self不可能为零吗?

我将根据您的问题尝试帮助您:

问题1)有很多正确的方法,每个开发人员都可以有自己的逻辑,但在这种情况下,我个人可能会这样做:

class A {    
    func f1 (_ completion: @escaping (String) -> void ){

        some asynchronous call ... { in
            ... 
            DispatchQueue.main.async { [weak self] in // 1
                guard let strongSelf = self else { return } // 2
                let varA = "something" // 3
                strongSelf.label.text = varA
                completion(varA) // 4
            }
        }
    }

    func f2 (_ string: String){

        another asynchronous call ... { in
            ... 
            DispatchQueue.main.async {
                sef.labelB.text = string // 5
            }
        }
    }

    // function call
    // 6
    f1(completion: { [weak self] text in
        guard let strongSelf = self else { return }
        strongSelf.f2(text)
    })
}
1-在这里,我使用[弱自我]来解决问题

2-只要打开可选的自我包装,如果它为零,我就返回

3-在您的例子中,实际上不需要类变量,所以我只是在块内创建局部变量

4-最后,我用包含字符串的变量调用completion

5-我也不需要在这里设置类变量,所以我只是用作为参数提供的字符串更新标签文本

6-然后,我只需要调用第一个函数,并在第一个函数完成后使用完成块调用第二个函数

问题2)是的,您必须调用
DispatchQueue.main
来更新视图。通过这种方式,您可以确保您的代码将在主线程中执行,这对于与UI交互的事情至关重要,因为它允许我们有一个您可以读入的sincronization点


问题3)使用
[弱自我]
guard let strongSelf=self-else{return}
,我将避免保留周期和
self
可能为
nil

的情况,我将根据您的问题尝试帮助您:

问题1)有很多正确的方法,每个开发人员都可以有自己的逻辑,但在这种情况下,我个人可能会这样做:

class A {    
    func f1 (_ completion: @escaping (String) -> void ){

        some asynchronous call ... { in
            ... 
            DispatchQueue.main.async { [weak self] in // 1
                guard let strongSelf = self else { return } // 2
                let varA = "something" // 3
                strongSelf.label.text = varA
                completion(varA) // 4
            }
        }
    }

    func f2 (_ string: String){

        another asynchronous call ... { in
            ... 
            DispatchQueue.main.async {
                sef.labelB.text = string // 5
            }
        }
    }

    // function call
    // 6
    f1(completion: { [weak self] text in
        guard let strongSelf = self else { return }
        strongSelf.f2(text)
    })
}
1-在这里,我使用[弱自我]来解决问题

2-只要打开可选的自我包装,如果它为零,我就返回

3-在您的例子中,实际上不需要类变量,所以我只是在块内创建局部变量

4-最后,我用包含字符串的变量调用completion

5-我也不需要在这里设置类变量,所以我只是用作为参数提供的字符串更新标签文本

6-然后,我只需要调用第一个函数,并在第一个函数完成后使用完成块调用第二个函数

问题2)是的,您必须调用
DispatchQueue.main
来更新视图。通过这种方式,您可以确保您的代码将在主线程中执行,这对于与UI交互的事情至关重要,因为它允许我们有一个您可以读入的sincronization点


问题3)使用
[弱自我]
guard-let-strongSelf=self-else{return}
,我避免了保留周期和
self
可能为
nil

的情况,这解释了一些问题。如果我只取出completion:func f1的一部分,然后分别运行f2(varA),会怎么样。如何确保设置varA后f2(varA)运行?由于异步函数有延迟返回,所以用self.f2(varA)替换completion(varA)是否可以,就像在某个asyn闭包中调用函数一样?用self.f2(varA)替换
completion(varA)
完全可以,因此您也要确保
f2
f1
完成后运行。通过使用
DispatchGroup
,还有另一种方法可以实现这一点,希望这个答案能在您决定这样做时帮助您:在f1的完成方法中,有一个f2调用,它也有一个完成,其中视图实际上正在主线程DispatchQueue.main.async上更新。这是否意味着在f1完成时,我们将在DispatchQueue.main.async{self.f2(varA)}中进行函数调用,或者不需要在主线程上进行调用?这就解释了一些问题。如果我只取出completion:func f1的一部分,然后分别运行f2(varA),会怎么样。如何确保设置varA后f2(varA)运行?由于异步函数有延迟返回,所以用self.f2(varA)替换completion(varA)是否可以,就像在某个asyn闭包中调用函数一样?用self.f2(varA)替换
completion(varA)
完全可以,因此您也要确保
f2
f1
完成后运行。通过使用
DispatchGroup
,还有另一种方法可以实现这一点,希望这个答案能在您决定这样做时帮助您:在f1的完成方法中,有一个f2调用,它也有一个完成,其中视图实际上正在主线程DispatchQueue.main.async上更新。这是否意味着在f1完成时,我们将在DispatchQueue.main.async{self.f2(varA)}中进行函数调用,或者不需要在主线程上调用该函数?