From what I understand, the RACSubject equivalent of ReactiveCocoa 4 is the Observer class.
I want to have a signal and an observer linked together so that the signal sends events applying a map operation to the events sent to the observer.
In Obj-C it looks like this:
// ViewModel.h
@interface ViewModel
@property (readonly) RACSubject *someAction; //expects e.g. int values
@property (readonly) RACSignal *someSignal; //sends e.g. string values
@end
// ViewModel.m
//redeclaring the signal and action as readwrite
@implementation
- (id)init {
_someAction = [RACSubject subject];
_someSignal = [_someAction map:^id(NSNumber *index) {
return "Some string based on index passed in";
}];
}
@end
Now when someone pushes a value onto someAction, the someSignal will fire an event containing a derived value.
How do I achieve the same effect in Swift?
What I've been able to do so far is something like this:
public class ViewModel: NSObject {
public let (internalSignal, someAction) = Signal<Int, NoError>.pipe()
public var someSignal: Signal<String, NoError> {
get {
return self.internalSignal.map({ [unowned self](index: Int) -> String in
return "Some string value based on \(self.someArray[index])"
})
}
}
public let someArray = [1, 2, 3, 4, 5]
}
Which looks like a bad solution because
internalSignalshould be private but needs to be declared public in order to match it to Signal's pipesomeSignalis computed every time it's needed therefore, even though the same signal could be reused over and over. Also can't be declared as aletconstant.
You could initialize the members in
initjust like ObjC...For
someSignalyou could also use lazy initialization, which allows the member to refer toself:Unlike the first piece of code, the lazy-var is initialized only before
someSignalis used, not at the ViewModel's initialization.Also, since it is a
var, Swift allows you use mutate its value (there is no such thing aslazy let). We can restrict the permission usingprivate(set), but this won't prevent you accidentally writeself.someSignal = ...somewhere.Alternatively, you could make
someSignalan implicitly unwrapped optional and initialize manually: