swift – 如何用RAC3替换我的KVO代码并保留现有模型?
发布时间:2020-12-14 04:55:43 所属栏目:百科 来源:网络整理
导读:我正在研究Reactive Cocoa来改进我们的 Swift代码.作为一个起点,我想将标签的文本绑定到属性的转换值.基本上,我想替换一些KVO代码.所以,我有以下变量: @IBOutlet weak var myLabel: UILabel!var myModel: MyModel 由于我们的模型是在Objective-C中开发的,My
我正在研究Reactive
Cocoa来改进我们的
Swift代码.作为一个起点,我想将标签的文本绑定到属性的转换值.基本上,我想替换一些KVO代码.所以,我有以下变量:
@IBOutlet weak var myLabel: UILabel! var myModel: MyModel 由于我们的模型是在Objective-C中开发的,MyModel看起来像这样: @interface MyModel : NSManagedObject @property (nonatomic,retain) NSNumber * value; @end 因此,我想做这样的事情: myLabel.text <~ myProperty.rac_signalForSelector("value") |> map { (value: NSNumber) in return "(value.integerValue + 1)" } 但是,这显然不起作用.我该如何处理这个问题? KVO如何通常用正常的模型属性实现? 我已经找到了关于这个主题的similar post.接受的答案建议使用ViewModels.但是,我不想用ViewModels替换现有的NSManagedObject模型,而是希望保留我的模型,因为我喜欢通过XCode管理它们并通过CoreData存储它们.或者这对ViewModels来说是否可行?我错过了什么关键吗? 解决方法
这样的事情(使用RAC 3.0.0使用Xcode 6.4构建):
/// 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 source:NSObject) { var (source_signal,source_sink) = Signal<AnyObject,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) } 在你的例子中你称之为: bind(propertyWithKey: "text",on: myTextField,toPropertyWithKey: "value",on: myProperty) { (number: NSNumber) in return "(number.integerValue)" as NSString } 我对ReactiveCocoa有些新意,所以上面的内容可能是一个天真的实现,但它可能会指向正确的方向. 更新 func bind<S,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) } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |