Wie wäre es damit so etwas wie (gebaut mit Xcode 6.4 RAC mit 3.0.0):
/// Send changes in the property value of a source object to another property on a target object,
/// optionally using a mapping function to convert values as necessary.
func bind<S, T>(propertyWithKey targetKey: String, on target: NSObject, toPropertyWithKey sourceKey: String, on source:NSObject, usingValueConversion sourceToTargetValueConversion: ((S) -> T)?) {
var (source_signal, source_sink) = Signal<T, NSError>.pipe()
var sourceSignalProducer = RACObserve(source, sourceKey).toSignalProducer()
|> start(next: {value in
if (value != nil) {
if (sourceToTargetValueConversion == nil) {
sendNext(source_sink, value as! T)
} else {
let mappedValue = sourceToTargetValueConversion!(value as! S)
sendNext(source_sink, mappedValue)
}
}
})
var convertedValueRACSignal = toRACSignal(
source_signal
|> map {(value: T) in value as! AnyObject}
)
convertedValueRACSignal ~> RAC(target, targetKey)
}
/// Send changes in the property value of a source object to another property on a target object.
/// No conversion of values or value types is performed between source and target.
func bind(propertyWithKey targetKey: String, on target: NSObject, toPropertyWithKey sourceKey: String, on source:NSObject) {
var (source_signal, source_sink) = Signal<AnyObject, NSError>.pipe()
var sourceSignalProducer = RACObserve(source, sourceKey).toSignalProducer()
|> start(next: {value in
if (value != nil) {
sendNext(source_sink, value!)
}
})
var convertedValueRACSignal = toRACSignal(source_signal)
convertedValueRACSignal ~> RAC(target, targetKey)
}
// From Colin Eberhardt's post at http://blog.scottlogic.com/2014/07/24/mvvm-reactivecocoa-swift.html
// a struct that replaces the RAC macro
struct RAC {
var target : NSObject!
var keyPath : String!
var nilValue : AnyObject!
init(_ target: NSObject!, _ keyPath: String, nilValue: AnyObject? = nil) {
self.target = target
self.keyPath = keyPath
self.nilValue = nilValue
}
func assignSignal(signal : RACSignal) {
signal.setKeyPath(self.keyPath, onObject: self.target, nilValue: self.nilValue)
}
}
// From Colin Eberhardt's post at http://blog.scottlogic.com/2014/07/24/mvvm-reactivecocoa-swift.html
infix operator ~> {}
func ~> (signal: RACSignal, rac: RAC) {
rac.assignSignal(signal)
}
// From Colin Eberhardt's post at http://blog.scottlogic.com/2014/07/24/mvvm-reactivecocoa-swift.html
func RACObserve(target: NSObject!, keyPath: String) -> RACSignal {
return target.rac_valuesForKeyPath(keyPath, observer: target)
}
In Ihrem Beispiel würden Sie es nennen:
bind(propertyWithKey: "text", on: myTextField, toPropertyWithKey: "value", on: myProperty)
{ (number: NSNumber) in
return "\(number.integerValue)" as NSString
}
ich etwas bin neu zu ReactiveCocoa, also ist das Obige wahrscheinlich eine naive Implementierung, aber es kann Sie in die richtige Richtung weisen.
aktualisieren Diese Implementierung von bind
unter Verwendung von Kanälen ist etwas kompakter und nutzt in KVO Unterstützung gebaut RAC ist:
func bind<S, T>(propertyWithKey targetKey: String, on target: NSObject, toPropertyWithKey sourceKey: String, on source:NSObject, usingValueConversion sourceToTargetValueConversion: ((S) -> T)?) {
var kvoChannelSource = RACKVOChannel(target: source, keyPath: sourceKey, nilValue: nil)
var sourceSignalWithoutNils = kvoChannelSource.followingTerminal
.filter { (var value:AnyObject?) -> Bool in
return (value != nil)
}
var mappedSourceSignal = sourceSignalWithoutNils
if (sourceToTargetValueConversion != nil)
{
mappedSourceSignal = sourceSignalWithoutNils.map { (var s: AnyObject!) -> AnyObject! in
var result : T = sourceToTargetValueConversion!(s as! S)
return result as! AnyObject
}
}
var kvoChannelTarget = RACKVOChannel(target: target, keyPath: targetKey, nilValue: nil)
mappedSourceSignal.subscribe(kvoChannelTarget.followingTerminal)
}