没有 subscribe/bind/drive 的 RxSwift 变量组合
RxSwift Variable composition without subscribe/bind/drive
我需要 viewModel 中的一些内部状态,但也试图遵循 "no subscription / bind / drive / ..." 理想的方法并且只在 Observables
之间进行组合。
如何指定 Variable
观察的内容?
示例:
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({ [=11=] != [] })
.map({ [=11=].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
})
})
}
"ideal approach"是为了避免使用Subjects/Variables。相反,支持序列发射器(return 可观察的函数)、序列接收器(接受可观察作为参数的函数)和序列转换器(两者都做的函数。)
序列发射器和接收器必然会产生副作用,并且在序列接收器内部,必须有一个subscribe/bind才能解压值并使用它。
发射器和接收器之间应该有直接和明显的link。 Subjects/Variables 倾向于打破 link.
在这种理想的方法中,您的 "view model" 不是包含一堆变量的 class/struct。您的视图模型是一个函数,它将 observables 作为参数,returns observables 供视图控制器绑定。例如:
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 \([=10=])!" }
return MyViewModel(label: label)
}
我需要 viewModel 中的一些内部状态,但也试图遵循 "no subscription / bind / drive / ..." 理想的方法并且只在 Observables
之间进行组合。
如何指定 Variable
观察的内容?
示例:
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({ [=11=] != [] })
.map({ [=11=].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
})
})
}
"ideal approach"是为了避免使用Subjects/Variables。相反,支持序列发射器(return 可观察的函数)、序列接收器(接受可观察作为参数的函数)和序列转换器(两者都做的函数。)
序列发射器和接收器必然会产生副作用,并且在序列接收器内部,必须有一个subscribe/bind才能解压值并使用它。
发射器和接收器之间应该有直接和明显的link。 Subjects/Variables 倾向于打破 link.
在这种理想的方法中,您的 "view model" 不是包含一堆变量的 class/struct。您的视图模型是一个函数,它将 observables 作为参数,returns observables 供视图控制器绑定。例如:
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 \([=10=])!" }
return MyViewModel(label: label)
}