Observable<String?>仅首次运行:KeychainManager绑定UI后状态不更新
解决RxSwift绑定后UI不更新的问题
这是个很典型的RxSwift状态绑定问题——你现在用的Observable.just只会发射一次初始值,后续accessToken的变化根本没法通知到UI绑定的序列里。要解决这个问题,核心是把accessToken变成可观察的状态容器,让它的变化能被RxSwift的订阅者感知到。
步骤1:重构KeychainManager,使用BehaviorRelay管理状态
我们需要用BehaviorRelay(RxSwift官方推荐的状态容器,替代已弃用的Variable)来包装accessToken,这样它的任何变化都会自动通知订阅者:
// 需要先导入 RxRelay 框架 import RxSwift import RxRelay internal struct KeychainManager { // 用私有的BehaviorRelay存储实际值,初始值为nil static private let _accessToken = BehaviorRelay<String?>(value: nil) // 对外保持原来的accessToken属性接口,内部转发到Relay static var accessToken: String? { get { _accessToken.value } set { _accessToken.accept(newValue) } } // 提供外部可订阅的Observable static var accessTokenObservable: Observable<String?> { _accessToken.asObservable() } }
这样修改后,你原来保存token的代码(比如KeychainManager.accessToken = "your_new_token")完全不需要改动——赋值操作会自动触发Relay发送新值。
步骤2:修改UI绑定代码,订阅可观察的状态序列
把原来的Observable.just换成我们提供的accessTokenObservable,这样就能实时接收accessToken的变化:
override func viewDidLoad() { super.viewDidLoad() KeychainManager.accessTokenObservable .debug() .map { $0 == nil } .bind(to: authenticateButton.rx.isEnabled) .disposed(by: disposeBag) }
为什么这样能解决问题?
Observable.just(KeychainManager.accessToken)只会在创建时发射一次当前的accessToken值,之后不管这个值怎么变,序列都不会再发射新数据,所以按钮状态永远不会更新。BehaviorRelay是一个持有当前状态的可观察序列:它会保存最新的accessToken值,每次调用accept(_:)更新值时,所有订阅它的观察者都会收到新值,从而触发UI的更新。
内容的提问来源于stack exchange,提问作者itsji10dra
相关产品推荐
相关产品推荐

