RxSwift 简单 withLatestFrom 不触发

Posted

技术标签:

【中文标题】RxSwift 简单 withLatestFrom 不触发【英文标题】:RxSwift simple withLatestFrom not firing 【发布时间】:2019-05-17 15:31:42 【问题描述】:

我有一个可观察的

lazy var user = _user.share(replay: 1)
private let _user = PublishRelay<User>()

UserState.swift 单例中。我的user observable 在应用程序加载后立即收到一个事件,并且我从后端收到一个用户。

稍后,在我的一个 ViewModel 中,我尝试

func profileViewModel(
    viewAppeared: Observable<Void>
) -> (
    title: Observable<String>
) 

    let title = viewAppeared.withLatestFrom(UserState.shared.user)  _, user in
        user.username
    

    return title


除非此事件永远不会触发(不要进入闭包),因为user 在订阅之前已经触发。

如何在 viewDidLoad 事件中完成此行为,我从我的 observable 中获取最新的 user 值?

编辑:

在我的单例初始化中,如果我随机输入一个user.subscribe()...,那么这一切都有效。我很困惑...

【问题讨论】:

你订阅了withLatestFrom返回的observable吗? 更新了答案以说明编辑代码中提供的新线索。见下文: 【参考方案1】:

我看到了问题。 PublishRelay 基本上只是一个 PublishSubject。

在您的 viewModel 订阅之前推送到它的任何内容都将丢失。 .share(replay: 1) 会有所帮助,除了在用户被推送到它之前需要订阅 that 的东西,以便它“捕获”事件并缓存后来的订阅者。

即使那样你也可能需要 .share(replay: 1, scope: .forever)。

您需要记住,您可以设置所有您想要的可观察链,但该链中的任何操作将在最终订阅该链之前执行。

将您的用户状态更改为 BehaviorSubject(值:nil)。如果用户被放到当前用户上,即使没有人订阅它,它也会捕获并保留当前用户。

然后在您的视图模型上执行以下操作。

class ProfileViewModel 
lazy var user = UserState.shared.user.compactMap  $0 
lazy var name = user.map  $0.username 
lazy var age = user.map  "\($0.age) years old" 
   .do(onNext:  print($0) 
// etc


class profileViewController 
  ...
  override func viewDidLoad() 
    ...
    profileViewModel.name
      .subscribe(onNext:  [weak self] name in 
        self?.title = name
      
      .disposed(by: disposeBag)
  

请注意,如果用户(以及用户名)可以在显示此视图控制器期间动态更改并且您希望自动更新标题,则您需要这样做。

另请注意,如图所示,您永远不会在 .do 语句中看到用户的年龄,因为目前没有订阅或绑定到该可观察子链。

【讨论】:

嗯,我尝试了share(replay:1) 路由,但似乎仍然没有触发我的流。 我编辑了一些帖子,我的 VC 在 vi​​ewDidLoad() 上调用了这个 viewModel 方法 @Brejuro 弄清楚发生了什么。查看修改后的答案。

以上是关于RxSwift 简单 withLatestFrom 不触发的主要内容,如果未能解决你的问题,请参考以下文章

为啥 withLatestFrom 不返回最新值?

如何从 rxjs 6 withLatestFrom 键入数组映射参数

将参数传递给 withLatestFrom 函数

[RxJS] Combination operator: withLatestFrom

为啥我使用有效的 withLatestFrom 操作从选择器获取具有动作观察者属性的对象?

RxJs操作符,其行为类似于withLatestFrom,但会等待第二个流的值。