【发布时间】:2020-04-09 18:58:36
【问题描述】:
我正在使用组合 Future 来环绕异步块操作并向该发布者添加订阅者以接收值。我注意到未来对象没有被解除分配,即使订阅者被解除分配。 XCode 内存图和仪器泄漏图本身没有显示对这些未来对象的引用。我很困惑为什么他们还在。
func getUsers(forceRefresh: Bool = false) -> AnyPublisher<[User], Error> {
let future = Future<[User], Error> { [weak self] promise in
guard let params = self?.params else {
promise(.failure(CustomErrors.invalidData))
return
}
self?.restApi.getUsers(params: params, forceRefresh: forceRefresh, success: { (users: [User]?, _) in
guard let users = users else {
return promise(.failure(CustomErrors.invalidData))
}
promise(.success(users))
}) { (error: Error) in
promise(.failure(error))
}
}
return future.eraseToAnyPublisher()
}
这是我添加订阅的方式:
self.userDataService?.getUsers(forceRefresh: forceRefresh)
.sink(receiveCompletion: { [weak self] completion in
self?.isLoading = false
if case let .failure(error) = completion {
self?.publisher.send(.error(error))
return
}
guard let users = self?.users, !users.isEmpty else {
self?.publisher.send(.empty)
return
}
self?.publisher.send(.data(users))
}) { [weak self] (response: Array<User>) in
self?.users = response
}.store(in: &self.subscribers)
deinit {
self.subscribers.removeAll()
}
这是上面创建的未来泄漏内存的屏幕截图。即使订阅者全部删除,它仍然存在。 Instruments 也展示了类似的内存图。有什么想法可能导致这种情况吗??
【问题讨论】:
-
你用调试器确认你进入了
deinit,对吗? -
是的,我做到了..流程中的所有其他对象都在被释放。我唯一的猜测是这个未来的承诺目前在异步操作完成块中得到解决。我在想可能是这个块在执行操作时没有被持有它的其他对象释放..
-
你能检查deinit是否被调用?我可能是错的,但不确定
store(in: &self.subscribers)是否会导致保留周期,您可以将其删除并将其分配给 AnyCancellable 变量吗? -
运气不好,同样的问题