swift 你能通过使用函数来避免闭包内存泄漏吗?

6tr1vspr  于 2023-02-28  发布在  Swift
关注(0)|答案(1)|浏览(159)

所以我使用RxSwiftfunction看起来像这样:

private func setAndVerifyTestmode(isOn: Bool) {
    parameterService.setTestMode(value: isOn)
      .flatMap { _ in self.parameterService.requestTestMode() }
      .subscribe( { [weak self] _ in
        //do stuff })
      .disposed(by: disposeBag)
}

我注意到我忘了在.flatMap中使用[weak self],所以我这样添加了它:

private func setAndVerifyTestmode(isOn: Bool) {
    parameterService.setTestMode(value: isOn)
      .flatMap { [weak self] (_: Int?) in 
          guard let self = self else { return .just(nil) }
          self.parameterService.requestTestMode() }
      .subscribe( { [weak self] _ in
        //do stuff })
      .disposed(by: disposeBag)
}

但它给了我一个错误:Generic parameter Result could not be infered
我无法解决这个问题,所以我尝试使用嵌套的function代替closure,结果如下:

private func setAndVerifyTestMode(isOn: Bool) {
    func requestTestMode(_: Int?) -> Single<Int?> {
      parameterService.requestTestMode()
    }
     
parameterService.setTestMode(value: isOn)
      .flatMap(requestTestMode(_:))
      .subscribe( { [weak self] _ in
        //do stuff })
      .disposed(by: disposeBag)
}

很好,编译器很满意,它工作了。在我的世界里,这解决了内存泄漏问题,因为我不再使用需要引用selfclosure但是,我的一个同事告诉我,这和在closure中不使用[weak self]是完全一样的;而且你仍然使用嵌套的function来服从memory leaks,我真的看不出它们是同一件事,因为甚至不再有对self的引用。
不管怎样,我的问题是:我是使用上面的嵌套函数来解决memory leaksself[weak self]的问题,还是我的同事说得对:都是一样的我所做的没有任何收获吗

xriantvc

xriantvc1#

但是,我的一个同事告诉我,这和在结束语中不使用[弱自我]是完全一样的;并且使用嵌套函数时仍然会发生内存泄漏。
你的同事说得对。(这让我很吃惊。)
幸运的是,还有更简单的方法:
最明显的是:.flatMap { [parameterService] _ in parameterService.requestTestMode() }通过直接捕获parameterService而不是通过self间接捕获,可以避免捕获self。
另一种选择:.flatMap { [weak self] _ in self?.parameterService.requestTestMode() ?? .just(0) }要发出的值有问题,因为您使用的是Single,所以必须发出一些东西。如果您使用的是Maybe或Observable,则可以只使用.empty()
像这样:.asMaybe().flatMap { [weak self] _ in self?.parameterService.requestTestMode().asMaybe() ?? .empty() }
最后你可以使用一个自由函数(一个不绑定到任何类或结构体的函数):

func requestTestMode(parameterService: ParameterService) -> (Int?) -> Single<Int?> {
    { _ in parameterService.requestTestMode() }
}

可以像这样使用:.flatMap(requestTestMode(parameterService: parameterService))这实际上和我上面给出的第一个选项是一样的。

相关问题