RxSwift中首个map解包的[weak self]为何可被后续所有运算符访问?
RxSwift链式调用中self访问的问题分析
核心误解澄清
你在第二个map中访问到的self,根本不是第一个map闭包内解包得到的局部self变量:
- 第一个map闭包内通过
guard let self = self得到的是闭包内部局部变量,作用域仅限定在第一个map的闭包大括号范围内,出了闭包就已经失效,不可能被后续运算符的闭包访问。 - 你第二个map闭包能访问到的
self,是当前ViewModel实例的原始强引用,因为你没有给第二个map的闭包声明[weak self]捕获列表,Swift闭包默认会对外部捕获的变量做强持有。 - 额外说明:你第一个map闭包中声明的
[weak self]捕获列表本身是多余的,因为你在第一个map的逻辑中完全没有用到self的相关能力。
潜在风险
这种写法必然会产生循环引用导致内存泄漏:
- 第二个map的闭包强持有了ViewModel实例(self)
- ViewModel实例通常会持有你定义的
textObservable作为属性 - 最终形成
self -> textObservable -> 第二个map闭包 -> self的引用环,双方都无法被正常释放。
推荐修复方案
有两种常用的安全写法:
方案1:给用到self的闭包统一加弱引用捕获
let textObservable = input.subject .map { [$0] } .map { [weak self] maps in guard let self = self else { return [] } return maps.map { self.makeString(string: $0) } }
方案2:使用RxSwift内置的withUnretained运算符(更简洁)
该运算符会自动弱持有目标对象,在对象释放时自动终止序列,避免重复写guard解包代码:
let textObservable = input.subject .withUnretained(self) .map { owner, value in [value] } .map { owner, maps in return maps.map { owner.makeString(string: $0) } }
内容的提问来源于stack exchange,提问作者NewBie
相关产品推荐
相关产品推荐

