iOS*_*eek 4 closures ios retain-cycle nsurlsession swift
我不知道我是否需要[weak self]在这种情况下使用?
HTTPClient.swift:
struct HTTPClient {
let session = URLSession.shared
func get(url: URL, completion: @escaping (Data) -> Void) {
session.dataTask(with: url) { data, urlResponse, error in
completion(data) // assume everything will go well
}.resume()
}
}
Run Code Online (Sandbox Code Playgroud)
服务.swift
struct Service {
let httpClient: HTTPClient
init(httpClient: HTTPClient = HTTPClient()) {
self.httpClient = httpClient
}
func fetchUser(completion: @escaping (User) -> Void) {
httpClient.get("urlToGetUser") { data in
// transform data to User
completion(user)
}
}
}
Run Code Online (Sandbox Code Playgroud)
视图模型.swift
class ViewModel {
let service: Service
let user: User?
var didLoadData: ((User) -> Void)?
init(service: Service) {
self.service = service
loadUser()
}
func loadUser() {
service.fetchUser { [weak self] user in // is [weak self] really needed ?
self?.user = user
self?.didLoadData?(user)
}
}
}
Run Code Online (Sandbox Code Playgroud)
用户真的需要这里[weak self]吗?当我们处理一个我们不知道闭包发生了什么的 API 时,是否有关于如何检查它是否需要的规则?或者这无关紧要(由我们决定)?
在您给出的示例中,[weak self]可能是不必要的。如果ViewModel在请求完成之前被释放,这取决于您想要发生的情况。
如URLSessionDataTask文档中所述(强调我的):
创建任务后,您可以通过调用它的 resume() 方法来启动它。然后会话保持对任务的强引用,直到请求完成或失败;你不需要维护对任务的引用,除非它对你的应用程序的内部簿记很有用。
会话对任务有很强的引用。任务对闭包有很强的引用。闭包对ViewModel. 只要ViewModel没有对任务的强引用(它在您提供的代码中没有),那么就没有循环。
问题是您是否要确保ViewModel继续存在足够长的时间来执行闭包。如果您这样做(或不关心),那么您可以使用简单的强引用。如果您想阻止任务保持ViewModel活动状态,那么您应该使用弱引用。
这就是您需要考虑参考周期的方式。没有一般规则“weak在这里使用”。weak当这就是你的意思时,你使用; 当你不希望这个闭包一直self存在直到它被释放时。如果它创建一个循环,则尤其如此。但是对于“这是否会产生循环”并没有统一的答案。这取决于哪些部分包含参考。
这也指出了您当前的 API 设计不如预期的好。你传递didLoadData在init。这很可能会创建引用循环并强制您的调用者使用weak. 相反,如果您在 上创建didLoadDdata了一个完成处理程序loadUser(),那么您可以避免该问题并使调用者的生活更轻松。
func loadUser(completion: @escaping ((User?) -> Void)? = nil) {
service.fetchUser {
self?.user = user
didLoadData?(user)
}
}
Run Code Online (Sandbox Code Playgroud)
(在任何情况下,您当前的 API 都存在竞争条件。您可以设置loadUser()之前开始didLoadData。您可能假设完成处理程序在您设置之前不会完成dataDidLoad,但没有真正的承诺。这可能是真的,但它充其量是脆弱的。)
| 归档时间: |
|
| 查看次数: |
2014 次 |
| 最近记录: |