Ios 不带订阅/绑定/驱动的RxSwift变量组合
我需要viewModel中的一些内部状态,但也尝试遵循“无订阅/绑定/驱动/…”的理想方法,只在Ios 不带订阅/绑定/驱动的RxSwift变量组合,ios,swift,rx-swift,reactivex,Ios,Swift,Rx Swift,Reactivex,我需要viewModel中的一些内部状态,但也尝试遵循“无订阅/绑定/驱动/…”的理想方法,只在可观察对象之间进行组合 如何指定变量观察到的内容 例如: private var userProfilesToFetch = Variable<[String]>([]) private var users: Variable<[User]> { return //something that observes fetchUserProfiles() and when
可观察对象之间进行组合
如何指定变量
观察到的内容
例如:
private var userProfilesToFetch = Variable<[String]>([])
private var users: Variable<[User]> {
return //something that observes fetchUserProfiles() and when it emits, appends to its .value
}
private func fetchUserProfiles() -> Observable<User?> {
let reference = databaseRef.child("users")
return userProfilesToFetch.asObservable()
.filter({ $0 != [] })
.map({ $0.last! })
.flatMap({ (userId) -> Observable<User?> in
return self.service.observeAllChildren(of: reference.child(userId), by: .value)
.map({ (snapshot) -> User? in
guard let values = snapshot.value as? [String: AnyObject] else { return nil }
var user = User(dictionary: values)
user.id = snapshot.key
return user
})
})
}
private var userProfilesToFetch=变量([])
私有var用户:变量{
return//观察fetchUserProfiles()并在其发出时附加到其.value的内容
}
private func fetchUserProfiles()->可观察{
let reference=databaseRef.child(“用户”)
返回userProfilesToFetch.asObservable()
.filter({$0!=[]})
.map({$0.last!})
.flatMap({(userId)->在
返回self.service.observeAllChildren(of:reference.child(userId),by:.value)
.map({(快照)->用户?在
guard let values=snapshot.value as?[String:AnyObject]else{return nil}
var user=user(字典:值)
user.id=snapshot.key
返回用户
})
})
}
理想方法是避免使用主题/变量。相反,更喜欢序列发射器(返回可观测值的函数)、序列接收器(接受可观测值作为参数的函数)和序列转换器(两者兼有的函数)
序列发射器和接收器必须执行副作用,在序列接收器内部,必须有一个订阅/绑定,以便解包并使用该值
发射器和接收器之间应该有直接和明显的联系。主题/变量往往会打破这种联系
在这种理想的方法中,您的“视图模型”不是包含一组变量的类/结构。视图模型是一个函数,它将观察值作为参数,并返回观察值供视图控制器绑定。例如:
class MyViewController: UIViewController {
@IBOutlet weak var name: UITextView!
@IBOutlet weak var label: UILabel!
override
func viewDidLoad() {
super.viewDidLoad()
let viewModel = myViewModel(name: name.rx.text.orEmpty)
viewModel.label.bind(to: label.rx.text).disposed(by: bag)
}
let bag = DisposeBag()
}
struct MyViewModel {
let label: Observable<String>
}
// this function could be turned into an `init` method on the MyViewModel struct if you would prefer.
fun myViewModel(name: Observable<String>) -> MyViewModel {
let label = name.map { "Hello \($0)!" }
return MyViewModel(label: label)
}
类MyViewController:UIViewController{
@ibvar名称:UITextView!
@IBVAR标签:UILabel!
推翻
func viewDidLoad(){
super.viewDidLoad()
让viewModel=myViewModel(名称:name.rx.text.orEmpty)
viewModel.label.bind(到:label.rx.text).处理(由:bag)
}
let bag=DisposeBag()
}
结构MyViewModel{
let标签:可观察
}
//如果愿意,可以将此函数转换为MyViewModel结构上的“init”方法。
有趣的myViewModel(名称:Observable)->myViewModel{
让label=name.map{“你好\($0)!”}
返回MyViewModel(标签:标签)
}
如果没有订阅或绑定,则不会发生任何事情。“被观察者是懒惰的,除非他们被观察到,否则不会做任何工作”。@DanielT。同意,但实现“最大关注点分离”的要点是在视图控制器中从调用中链接订阅。问题是我不知道如何在订阅链中包含变量。例如,如果在我的VC中,我在我的viewModel中订阅了(A),那么因为这(A)绑定到其定义中的另一个可观察对象,比如上面的fetchUserProfiles()
函数,它将链接subscribe touserProfilesToFetch
等等。我不明白的是如何通过指定变量应该观察的内容来链接变量本身。确切地说,我一直在尝试避免使用任何类型的主题,但出于某种原因,我感觉我的复杂用例“需要状态”。我想这都是我自己的局限,我放弃了寻找没有它们的正确方法,更因为我找不到一个“复杂”的RxSwift应用程序可以学习。你的回复给了我新的想法,我会重新思考这个问题。谢谢!这里有一个复杂的例子:它是一个视图模型,处理按需从服务器下载页面中的数据。它包括一个完整的测试套件。如果你对此有任何疑问,可以在这里发布,或者作为对要点的评论。是的,它包含一个变量,有时它们是不可避免的。