【问题标题】:Escaping closure setting views in DispatchQueue.main.async Swift 3在 DispatchQueue.main.async Swift 3 中转义关闭设置视图
【发布时间】:2018-01-11 19:01:37
【问题描述】:

我正在处理一些异步函数并尝试更新视图。简而言之,我有一个带有异步函数的函数 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 为零?

【问题讨论】:

    标签: asynchronous swift3 callback closures dispatch


    【解决方案1】:

    我会根据你的问题尝试帮助你:

    问题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 - 这里我使用 [weak self] 来表示avoid retain cycles

    2 - 只是解开可选的 self,如果它是 nil,我就返回。

    3 - 在你的情况下,类变量并不是真正需要的,所以我只是在块内创建局部变量。

    4 - 最后,我使用包含字符串的变量调用完成。

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

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

    问题 2) 是的,您必须致电 DispatchQueue.main 来更新视图。这样,您可以确保您的代码将在主线程中执行,这对于与 UI 交互的事物至关重要,因为它允许我们有一个 sincronization 点,您可以在 Apple's documentation 中阅读。

    问题 3) 使用[weak self]guard let strongSelf = self else { return },我避免了保留周期以及self 可以是nil 的情况。

    【讨论】:

    • 这说明了一些事情。如果我只是取出完成:func f1 的一部分并单独运行 f2(varA) 怎么办。如何确保 f2(varA) 在 varA 设置后运行?因为异步函数有延迟返回
    • 也可以用self.f2(varA)替换completion(varA),就像在一些异步闭包中调用函数一样吗?
    • self.f2(varA) 替换completion(varA) 完全没问题,因此您还要确保f2f1 完成后运行。还有另一种方法可以通过使用DispatchGroup 来实现,希望这个答案可以帮助你,以防你决定这样做:stackoverflow.com/questions/43689685/…
    • 在 f1 的完成方法中有 f2 调用,它也有一个完成,其中视图实际上正在主线程 DispatchQueue.main.async 上更新。这是否意味着在 f1 完成时,我们将在 DispatchQueue.main.async { self.f2(varA) } 中进行函数调用,还是不需要在主线程上调用它?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多