swift 3 : capture strong self in @escaping closure without asynchronous work

标签 swift asynchronous grand-central-dispatch dispatch-async

有一个带有以下声明的协议(protocol):

typealias SuggestionSourceCallback = ([Suggestion]) -> ()

protocol SuggestionSource {
    func suggest(_ query: SuggestionQuery, callback: @escaping SuggestionSourceCallback)
}

有两个类实现了这个协议(protocol)。第一类异步获取建议(通过 GCD )

final class FisrtClass: SuggestionSource {
    private let queue = DispatchQueue(label: "my.app.queue", attributes: [])
    private var lastQuery: SuggestionQuery?
    // ...
    func suggest(_ query: SuggestionQuery, callback: @escaping SuggestionSourceCallback) { 
        self.queue.async { [weak self] in

            // capturing strong self
            guard let strongSelf = self else {
                return
            }

            // referencing self here, for example
            guard self.lastQuery == query else {
                return
            }

            // suggestions is a local variable
            var suggestions: [Suggestion] = []

            // ... 

            DispatchQueue.main.async {
                callback(suggestions)
            }
        }
    }
}

...而第二类同步进行

final class SecondClass: SuggestionSource {
    // ...
    func suggest(_ query: SuggestionQuery, callback: @escaping SuggestionSourceCallback) {
        // ...
        callback(self.suggestions[query])
    }
}

我的问题是:

  1. 我应该在 FirstClass 的实现中捕获 strongSelf 吗?
  2. 我应该在 SecondsClass 的实现中捕获 strongSelf 吗?

更新

附加问题。假设 SecondClass 有它的 suggestions 作为一个 static let,在这种情况下会是什么模式?

final class SecondClass: SuggestionSource {
    static let suggestions: [String: [SuggestionQuery]] = {
         // ...
    }()

    // ...
    func suggest(_ query: SuggestionQuery, callback: @escaping SuggestionSourceCallback) {
        // ...
        callback(self.suggestions[query])
    }
}

最佳答案

SecondClass中,不需要创建strongSelf变量。你会把它放在哪里?关键是 self 无论如何都保证不会是 nil,因为您正在其方法之一的范围内运行。

您的附加问题也是如此,但出于不同的原因。 suggestions 现在是 static,所以用 self 作为前缀是一个语法问题,(我假设你也想为 suggest 添加前缀 方法与 static)。

但是,在 FirstClass 中,捕获 strongSelf 和不捕获它之间存在细微差别。

因为您使用的是[weak self],所以当您进入该 block 时,self 可能是nil,所以无论如何您都需要检查一下.一种方法是重复使用可选链接,即:

self?.doSomething()
self?.doSomethingElse()

这是在说:

If I have a reference to self, do something. If I still have a reference to self, do something else.

通过添加一个 strongSelf 变量:

guard let strongSelf = self else {
  return
}
strongSelf.doSomething()
strongSelf.doSomethingElse()

...你是说:

do something and do something else if you have a reference to self, otherwise do nothing.

因此,您保证如果第一件事发生,第二件事也会发生。您采用的方法将取决于您的应用。

关于 swift 3 : capture strong self in @escaping closure without asynchronous work,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40844049/

相关文章:

swift - IBDesignable XIB 由于加载方法而抛出错误

ios - 我想要一个 UIView 覆盖整个屏幕甚至导航栏,但显示它的 subview

c# - 异步图像加载到列表框中

swift - 为什么使用 GCD 的 Swift CLI 代码与不使用并发的代码运行速度相同?

ios - 是什么导致 libdispatch-manager 线程崩溃?

ios - 如何裁剪 UIScrollView 中显示的 UIImageView 部分并将其保存到 UIImage 变量?

ios - 当 Firebase 函数以 Swift 结束时

javascript - 测试复杂的异步 Redux 操作

c# - 围绕异步等待

ios - 如何解决 dispatch_group_leave 崩溃