【问题标题】:Combine Future publisher is leaking结合未来的出版商正在泄漏
【发布时间】:2021-04-09 12:03:15
【问题描述】:

嗨,所以我正在尝试用 Combine 的 Future/Promise 包装一个异步网络请求。

我的代码是这样的:

enum State {
    case initial
    case loading
    case success(movies: [Movie])
    case error(message: String)
}

protocol ViewModelProtocol {

    var statePublisher: AnyPublisher<State, Never> { get }

    func load(genreId: String)
}

class ViewModel: ViewModelProtocol {

   var remoteDataSource = RemoteDataSource()

   @Published state: State = .initial
   var statePublisher: AnyPublisher<State, Never> { $state.eraseToAnyPubliher() }

   public func load(genreId: String) {
        self.state = .loading
        self.getMovies(for: genreId)
            .sink { [weak self] (moveis) in
                guard let self = self else { return }
                if let movies = movies {
                    self.state = .success(movies: movies)
                } else {
                    self.state = .error(message: "failed to load movies")
                }
            }
   }


func getMovies(for genreId: String) -> AnyPublisher<[Movie]?, Never> {
        Future {  promise in
            self.remoteDataSource.getMovies(for: genreId) { (result) in
                switch result {
                case .success(let movies): promise(.success(movies))
                case .failure: promise(.success(nil))
                }
            }
        }.eraseToAnyPublisher()
   }
}

我试图查看是否有任何内存泄漏,发现有一个未释放的对 Future 的引用 和这里一样:Combine Future Publisher is not getting deallocated

【问题讨论】:

  • 代码量不足以重现内存泄漏。如果您不确定如何在链接到的答案中应用该建议,他们的建议是将Future 包装在Deferred 发布者中:Deferred { Future { ...} }.eraseToAnyPublisher()。但同样 - 在这里还不足以得出结论这是否会解决您的内存泄漏
  • 嘿@NewDev 感谢重播,我添加了使用它的其余代码,其余的只是视图控制器绑定到状态变量并相应地渲染屏幕

标签: ios swift memory-leaks combine


【解决方案1】:

您在逃逸的 Future init 中强烈地捕获了 self(只需捕获 remoteDataSource)。在我看来,这似乎不会导致内存泄漏。正如您在问题中提出的链接所暗示的那样,Future 的行为与大多数其他出版商不同;它在您创建后立即起作用,而不是在您订阅时。它还记忆并分享其结果。我强烈建议您不要在 AnyPublisher 后面使用它,因为对于调用者来说,这东西由 Future 支持并且它将立即开始工作,这并不明显。我会改用 URLSession.shared.dataTaskPublisher,然后你会得到一个普通的发布者,你不需要完成处理程序或 Future。否则将 Future 包装在 Deferred 中,这样您就不会得到急切的评估。

【讨论】:

    猜你喜欢
    • 2023-03-18
    • 2021-05-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-11
    • 1970-01-01
    相关资源
    最近更新 更多