Grazie per sollevare la questione, ho trascorso qualche tempo a scavare intorno al ControlProperty
implementazione (nota ho aggiunto una chiamata .debug()
per tracciare i valori generati per la proprietà di controllo).
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)
}
}
}
La mia configurazione di prova era come seguendo, ho rimosso tutte le viste posizionamento qui per renderlo più breve:
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)
}
Ora per i risultati. Per prima cosa proviamo a premere il pulsante, che dovrebbe impostare la variabile su true
. Ciò attiva on(event: Event<E>)
in ControlProperty e imposta il valore dello switch su 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`)
Successivamente consente di attivare l'interruttore stesso. Quindi, come possiamo vedere, il controllo ha generato un evento come risultato di UIControlEventValueChanged
che è stato passato attraverso _values
in ControlProperty e quindi il suo valore è stato assegnato al valore Variable
come nell'esempio sopra. Ma non c'è un ciclo, poiché l'aggiornamento al valore Variable
non attiva un evento di controllo sullo switch.
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`)
Quindi una spiegazione semplice sarebbe:
- un valore da un controllo viene emesso una volta una sorta di
UIControlEvent
viene attivato
- quando un valore è assegnato direttamente alla proprietà di controllo, il controllo non innesca un evento di cambiamento quindi non c'è loop.
Speranza che aiuta, mi spiace per una spiegazione disordinato po '- ho trovato da esperimento)
Bell'esempio con Variable <-> variabile. Tuttavia non riesco a farlo funzionare con array come Variable <[URL]>. Eventuali suggerimenti? – mkkrolik