lei*_*701 9 functional-programming ios reactive-cocoa swift rx-swift
我在RxSwift的示例代码中读取了双向绑定运算符.
func <-> <T>(property: ControlProperty<T>, variable: Variable<T>) -> Disposable {
let bindToUIDisposable = variable.asObservable()
.bindTo(property)
let bindToVariable = property
.subscribe(onNext: { n in
variable.value = n
}, onCompleted: {
bindToUIDisposable.dispose()
})
return StableCompositeDisposable.create(bindToUIDisposable, bindToVariable)
}
Run Code Online (Sandbox Code Playgroud)
当property改变,它会通知变量,并设置变量的值,而该变量的值时,它会通知物业.我认为这会导致无休止的循环......
Sco*_*ner 15
我相信你可以使用bindTo.以下是ControlProperty <-> Variable和的实现Variable <-> Variable:
infix operator <-> { precedence 130 associativity left }
func <-><T: Comparable>(property: ControlProperty<T>, variable: Variable<T>) -> Disposable {
let variableToProperty = variable.asObservable()
.distinctUntilChanged()
.bindTo(property)
let propertyToVariable = property
.distinctUntilChanged()
.bindTo(variable)
return StableCompositeDisposable.create(variableToProperty, propertyToVariable)
}
func <-><T: Comparable>(left: Variable<T>, right: Variable<T>) -> Disposable {
let leftToRight = left.asObservable()
.distinctUntilChanged()
.bindTo(right)
let rightToLeft = right.asObservable()
.distinctUntilChanged()
.bindTo(left)
return StableCompositeDisposable.create(leftToRight, rightToLeft)
}
Run Code Online (Sandbox Code Playgroud)
的实例ControlProperty <-> Variable(如UITextField和UITextView)处于RxSwiftPlayer项目
// Example of Variable <-> Variable
let disposeBag = DisposeBag()
let var1 = Variable(1)
let var2 = Variable(2)
(var1 <-> var2).addDisposableTo(disposeBag)
var1.value = 10
print(var2.value) // 10
var2.value = 20
print(var1.value) // 20
Run Code Online (Sandbox Code Playgroud)
感谢提出问题,我花了一些时间来挖掘ControlProperty实现(注意我已经添加了一个.debug()跟踪控件属性生成的值的调用).
public struct ControlProperty<PropertyType> : ControlPropertyType {
public typealias E = PropertyType
let _values: Observable<PropertyType>
let _valueSink: AnyObserver<PropertyType>
public init<V: ObservableType, S: ObserverType where E == V.E, E == S.E>(values: V, valueSink: S) {
_values = values.debug("Control property values").subscribeOn(ConcurrentMainScheduler.instance)
_valueSink = valueSink.asObserver()
}
public func on(event: Event<E>) {
switch event {
case .Error(let error):
bindingErrorToInterface(error)
case .Next:
_valueSink.on(event)
case .Completed:
_valueSink.on(event)
}
}
}
Run Code Online (Sandbox Code Playgroud)
我的测试设置如下,我删除了所有位于此处的视图以缩短它:
import UIKit
import RxSwift
import RxCocoa
class ViewController: UIViewController {
let variable = Variable<Bool>(false);
let bag = DisposeBag();
override func loadView() {
super.loadView()
let aSwitch = UISwitch();
view.addSubview(aSwitch)
(aSwitch.rx_value <-> variable).addDisposableTo(bag);
let button = UIButton();
button.rx_tap.subscribeNext { [weak self] in
self?.variable.value = true;
}.addDisposableTo(bag)
view.addSubview(button);
}
}
infix operator <-> {
}
func <-> <T>(property: ControlProperty<T>, variable: Variable<T>) -> Disposable{
let bindToUIDisposable = variable.asObservable().debug("Variable values in bind")
.bindTo(property)
let bindToVariable = property
.debug("Property values in bind")
.subscribe(onNext: { n in
variable.value = n
}, onCompleted: {
bindToUIDisposable.dispose()
})
return StableCompositeDisposable.create(bindToUIDisposable, bindToVariable)
}
Run Code Online (Sandbox Code Playgroud)
现在结果.首先我们尝试点击按钮,该按钮应该将变量设置为true.这将on(event: Event<E>)在ControlProperty上触发并将开关值设置为true.
2016-05-28 12:24:33.229: Variable values in bind -> Event Next(true)
// value flow
value assigned to Variable ->
Variable emits event ->
ControlProperty receives event ->
value assigned to underlying control property (e.g. `on` for `UISwitch`)
Run Code Online (Sandbox Code Playgroud)
接下来让我们触发开关.正如我们所看到的,控件生成了一个事件,其结果UIControlEventValueChanged是_values在ControlProperty上传递,然后将其值分配给Variable值,如上例所示.但是没有循环,因为更新Variable值不会触发交换机上的控制事件.
2016-05-28 12:29:01.957: Control property values -> Event Next(false)
2016-05-28 12:29:01.957: Property values in bind -> Event Next(false)
2016-05-28 12:29:01.958: Variable values in bind -> Event Next(false)
// value flow
trigger the state of control (e.g. `UISwitch`) ->
ControlProperty emits event ->
value assigned to Variable ->
Variable emits event ->
ControlProperty receives event ->
value assigned to underlying control property (e.g. `on` for `UISwitch`)
Run Code Online (Sandbox Code Playgroud)
所以一个简单的解释是:
UIControlEvent触发某种控制,就会发出控制值希望它有所帮助,抱歉有点凌乱的解释 - 我通过实验找到了它)
您输入任何内容,5 秒后就会清楚。这是从上面的答案中获取的
import UIKit
import RxSwift
import RxCocoa
class UserViewModel {
let username = BehaviorSubject<String?>(value: "")
}
class ViewController: UIViewController {
@IBOutlet weak var email: UITextField!
var userViewModel = UserViewModel()
let bag = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
userViewModel.username.asObservable().subscribe { print($0) }.disposed(by: bag)
(email.rx.text <-> userViewModel.username).disposed(by: bag)
// clear value of the username.
DispatchQueue.main.asyncAfter(deadline: .now()+5) {
self.userViewModel.username.onNext(nil)
}
}
}
infix operator <->
@discardableResult func <-><T>(property: ControlProperty<T>, variable: BehaviorSubject<T>) -> Disposable {
let variableToProperty = variable.asObservable()
.bind(to: property)
let propertyToVariable = property
.subscribe(
onNext: { variable.onNext($0) },
onCompleted: { variableToProperty.dispose() }
)
return Disposables.create(variableToProperty, propertyToVariable)
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
9914 次 |
| 最近记录: |