You can drastically simplify this case by moving the movieModel from the static to the dynamic part of the RACObserve macro: RAC(self.titleLabel, text) = RACObserve(self, movieModel.title); Then, your view will update both when the model instances are exchanged and when a model instance itself changes. If your view model contains...
ios,reactive-programming,reactive-cocoa,racsignal
First of all, the each5SecondSignal can be much simpler. You don't have to call take: as it will cause the signal to complete after 5 seconds, and if I understood you correctly you want the signal to go on forever. RACSignal *each5SecondSignal = [RACSignal interval:5 onScheduler:[RACScheduler mainThreadScheduler]] And you can...
objective-c,cocoa,reactive-cocoa,raccommand
I'm a bit new to RACCommand, so I'm not certain there's a better way to do this. But I have been using takeUntil: with a cancellation signal to halt execution. RACCommand *command = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) { return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) { while (true) { [subscriber sendNext:nil];...
objective-c,refactoring,afnetworking-2,reactive-cocoa
This is untested, but should get you most of the way there: - (RACSignal *)GET:(NSString *)url parameters:(NSDictionary *)parameters { SEL sel = @selector(GET:parameters:success:failure:); return [self signalForRequest:sel url:url parameters:parameters]; } - (RACSignal *)POST:(NSString *)url parameters:(NSDictionary *)parameters { SEL sel = @selector(POST:parameters:success:failure:); return [self signalForRequest:sel url:url parameters:parameters]; } - (RACSignal *)PUT:(NSString *)url...
swift,cocoa-touch,scenekit,reactive-cocoa
I would recommend you having a look at this course by Stanford University and having a look at the MVC lectures: https://itunes.apple.com/gb/course/developing-ios-8-apps-swift/id961180099 They recommend using NSNotifications to alert your controller (which in your case could be your SCNScene) of changes in your model. Your controller then goes and makes changes...
For lack of time, I'll go with a more laconic answer compared to @IanHenry's :) For anything here that doesn't make sense, please comment and I'll be happy explain in detail. // Map additions into blocks that add the bookmark to the given mutable array. RACSignal *addBookmarkSignal = [[addBookmarkCommand concat]...
Finally, with help from powerj1984 I created this method for now: extension RACSignal { func ignoreNil() -> RACSignal { return self.filter({ (innerValue) -> Bool in return innerValue != nil }) } } ...
ios,objective-c,functional-programming,reactive-programming,reactive-cocoa
I got some help at the GitHub page for ReactiveCocoa : You can use -flattenMap: to do this since it lets you return a signal instead of just a single value: RAC(self.displayLink, paused) = [changeSignal flattenMap:^id(RACTuple *value) { RACSignal *pauseSignal = [RACSignal return:@([((NSMutableArray *)value.first) count] == 0)]; if (pause) {...
There's no one answer, some code will call -setFrame:, while other code will call -setBounds:. If the code that sets the rect is not your code, then you could observe both bounds and frame and merge the two signals. For example: [[[RACSignal merge:@[RACObserve(view, frame), RACObserve(view, bounds)]] logNext] map:^(NSValue *value) {...
ios,objective-c,core-data,mvvm,reactive-cocoa
The race condition may be that name2IsValidSignal can be true before name1IsValidSignal is false. Which means that isValidSignal can be true momentarily before turning false (which would trigger the save). One solution is to combine the validation logic into a single unit: self.isValidSignal = [RACSignal combineLatest:@[RACObserve(self, name1), RACObserve(self, name2)] reduce:^id(NSString...
ios,objective-c,reactive-cocoa
Unfortunately there's no good way to "lift" a protocol method that returns a value, since it'd require that the signal is synchronous. Could you disable the text view instead?
RAC(self.lbl, userName) = RACObserve(self.viewModel, user.userName); The comma denotes the break between the "static" part (self.viewModel) and the dynamic, changing part (user.userName). This is a really nice feature of RACObserve, but you could implement this yourself, to modify Leo's answer so that it works with a changing userName: map not into...
ios,objective-c,reactive-programming,reactive-cocoa
You can simplify the nesting a bit by using the then helper, which will simplify error handling and prevent the separate twitterLoginCommand.errors subscription: [self.viewModel.twitterLoginCommand.executionSignals subscribeNext:^(id x) { [x then:^{ NSLog(@"%@", @"completed"); [ALTAlert wait:@""]; return [self.viewModel appLoginWithTwitter]; }] subscribeNext:^(id x) { NSLog(@"%@", x); } error:^(NSError *error) { [ALTAlert dismiss]; [ALTAlert error:error.localizedDescription];...
objective-c,forms,dynamic,reactive-cocoa,racsignal
Fo your first question, you can use map along with RACTuple: @property (assign, nonatomic) BOOL formComplete; - (void)setUpSignals { NSMutableArray *fieldCompleteSignals = [NSMutableArray arrayWithCapacity:self.fields.count]; for (Field *field in self.fields) { RACSignal *completeSignal = [field complete]; [fieldCompleteSignals addObject:completeSignal]; } RAC(self, formComplete) = [[RACSignal combineLatest:self.fieldCompleteSignals] map:^id (RACTuple *allValues) { return @([allValues.rac_sequence all:^BOOL(id...
ios,key-value-observing,reactive-cocoa,key-value-coding,kvc
What you are probably looking for is the following: [[keyValueCodingArray rac_signalForSelector:@selector(addObject:)] subscribeNext:^(id x) { <#code#> }]; and [[keyValueCodingArray rac_signalForSelector:@selector(removeObject:)] subscribeNext:^(id x) { <#code#> }]; Your code only checks the changes on the array property, not calls to it's value....
-throttle: accepts an NSTimeInterval, which is a floating-point specification of seconds, not milliseconds. Given the code in the question, I expect you would see results after 500 seconds have elapsed....
Your question can be generalised to "What are the advantages of signals over callbacks". There used to be a link on RAC's github repo called Escape from Callback Hell - link is no longer working, but I think that title highlights the point perfectly. Basically, one of the advantages of...
objective-c,objective-c-blocks,reactive-cocoa
I know it looks horrible, but as I'm using Objective-C++ this thing goes crazy. I solve this thing by casting it to id and it works... don't ask me why. RACSignal* contactIdentifierSignal = RACObserve(self, contactIdentifier); RACSignal* displayNameSignal = RACObserve(self, displayName); RACSignal* mappedThing = [RACSignal combineLatest:@[contactIdentifierSignal, displayNameSignal] reduce:(id)^id(NSString* identifierValue, NSString* displayNameValue){...
The observation is backwards. Try: userLocation.rac_valuesForKeyPath("newLocation", observer: self).subscribeNextAs { (value) -> () in println("New location received!") } ...
You should in my opinion use RACCommand : RACCommand* command = [[RACCommand alloc] initWithSignalBlock:^(id _) { return [#mysignal]; }]; // then later [command execute:nil]; // or [[command execute:nil] take:1];// synchronous but be careful ! here be dragons You can call execute as many time as you want, it wont subscribe...
If you mean they're synced with one property, something like this: [RACAble(self.buttonTitle) subscribeNext:^(NSString *newTitle) { NSString *normalTitle = [NSString stringWithFormat:@"Normal %@", newTitle]; NSString *highlightedTitle = [NSString stringWithFormat:@"Highlighted %@", newTitle]; [self.button setTitle:normalTitle forState:UIControlStateNormal]; [self.button setTitle:highlightedTitle forState:UIControlStateHighlighted]; }]; If you mean there're two properties, something like this: [RACAble(self.normalButtonTitle)...
ios,objective-c,reactive-programming,reactive-cocoa
First of all, in order to change the button's title, you have to call its setTitle:forState: method. Also please note that using self inside the subscribeNext block is likely to create a retain cycle (and therefore a memory leak). You can read more about it in this answer. You can...
ios,swift,compiler-errors,reactive-cocoa
Typo is in argument of doError() (and incorrectly identified by compiler): it should be of type (NSError!) -> Void instead of (NSError) -> Void. Modified like this it compiles fine: loginButton.rac_command.executionSignals.flatten() .logAll() .doError { (err:NSError!) -> Void in println(err.description) } .subscribeNext { (_:AnyObject!) -> Void in println("Sent next") } Additional...
ios,objective-c,reactive-cocoa
I take it that whole block is wrapped in a createSignal:, hence the calls to subscriber. But that's probably not necessary. Instead of: RACSignal *imageSignal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber>subscriber) { [[[imageSearch filter:^BOOL(NSString *path) { ... Just assign it to be a derived signal: RACSignal *imageSignal = [[[imageSearch filter:^BOOL(NSString *path) {...
ios,functional-programming,reactive-cocoa
One is pull driven (RACSequence) and the other is push driven (RACSignal). From here: Push-driven means that values for the signal are not defined at the moment of signal creation and may become available at a later time (for example, as a result from network request, or any user input)....
ios,objective-c,reactive-cocoa
The ignore operation on an RACSignal can be used to filter out specific values: [[RACObserve(self, maybeNilProperty) ignore:nil] subscribeNext:^(id x) { // x can't be nil }]; ...
The method -repeatFunc: captures an immutable reference to its own pointer to dc, and so each repeat sends that reference, not the local reference which you have nil'd out. It could be done like so: __block DataClass *dc = [[DataClass alloc] init]; RACSignal *signal = [[[RACSignal defer:^{ return [RACSignal return:dc];...
You should be able to accomplish this with +zip:reduce: RACSignal *arraySig = [@[@1, @2, @3].rac_sequence signal]; RACSubject *triggerSig = [RACSubject subject]; [[RACSignal zip:@[arraySig, triggerSig] reduce:^id(id arrayVal, id triggerVal) { return arrayVal; }] subscribeNext:^(id x) { DDLogVerbose(@"Subscriber got %@ from array", x); }]; [triggerSig sendNext:@"Give me data!"]; The zip operation waits...
If you want to start writing more RAC-based code, then I would highly encourage you to use a RACSignal instead of a value property, for two reasons: RACSignal use on view models is arguably more idiomatic (i.e.: a more "RAC" way of doing things). Not having access to the property...
ios,objective-c,reactive-cocoa
I found the cause of this problem, though I do not know the reason how it triggered this error. In my Podfile, I have included ReactiveCocoa pod in both the application and test targets. Removing the ReactiveCocoa pod from the test target resolves the issue. Original version having issues: target...
Two things: The order does matter, since this is a subject, so change it to this: RACSubject *test = [[RACSubject alloc] init]; [test flattenMap:^RACStream *(id value) { NSLog(@"here: %@", value); return [RACSignal return:@NO]; }]; [test sendNext:@1]; [test sendNext:@2]; [test sendCompleted]; Now, you're still not going to see anything -- because...
swift,reactive-cocoa,racsignal
There is! I think you're looking for interval:onScheduler:. It will emit the current NSDate, which is usually not that useful, so you can use it to sample another signal that has the data you want. For example, with a constant value: [[RACSignal return:@20] sample:[RACSignal interval:1.0 onScheduler:[RACScheduler mainThreadScheduler]]]; Edit: ...or you...
ios,objective-c,reactive-cocoa
ReactiveCocoa has a construct exactly for this situation called tryMap:. Check it out: [signal tryMap:^id(NSDictionary *dictionary, NSError **errorPtr) { return [MTLJSONAdapter modelOfClass:SAMWebServiceResponse.class fromJSONDictionary:dictionary error:errorPtr]; }] This assumes that modelOfClass:fromJSONDictionary:error: will return nil when an error occurs -- which is pretty standard -- but it's worth checking the docs on that...
ios,objective-c,reactive-cocoa
Ok. While creating the test project I found the problem. As stupid as it was, the class which created the Settings object wasn't registered for the test target. Don't ask me why it was compiling and running until it crashed...
reactive-programming,reactive-cocoa
Just to give an example for other viewers, a way to make sure that you're not fetching any images from a model that is nil - one could do something like: RAC(self.someImageView, image) = [[RACObserve(self, model) filter:^BOOL(PhotoModel *currentModel) { return currentModel != nil; }] map:^id(PhotoModel *currentModel) { return [self someMethodToDownloadImageFromModel:currentModel];...
ios,objective-c,reactive-cocoa,nsmutableset
I'd imagine you're not getting the notification since you're observing a pointer to selectedEmails, and as far as ReactiveCocoa is concerned, this value has not changed. The information contained at that location has changed (i.e. the object has been mutated), but the pointer itself is still referencing the same object....
ios,mvvm,uitableview,viewmodel,reactive-cocoa
Ok - I figured it out. The labels where all nil in initWithCoder: - so I had to postpone the RAC() binding until the everything is loaded from the nib. - (void)awakeFromNib { [super awakeFromNib]; RAC(self.workoutNameLabel, text) = RACObserve(self, viewModel.workoutName); RAC(self.numberOfExercisesLabel, text) = RACObserve(self, viewModel.numberOfExercises); } And now the labels...
ios,objective-c,reactive-cocoa
Although I don't have self-confidence in understanding what you are meaning, I recommend using "map", instead of the combination of "createSignal" and "flattenMap". Like this. - (RACSignal *) fetchNearbyDatasForLocation: (CLLocationCoordinate2D)coordinate { return [[self.apiClient fetchNearbyDatasforLocation:coordinate] flattenMap:^RACStream *(NSArray* datas) { /* ... */; return [[RACSignal combineLatest:signals] map:^(RACTuple *unused) { return datas; }]];...
It might be represented like that using -[RACMulticastConnection autoconnect]: RACSignal* data1FromNetwork = ...; RACSignal* data1FromNetworkHub = [[data1FromNetwork publish] autoconnect]; // Or below if you want replaying behavior. // RACSignal* data1FromNetworkHub = [[data1FromNetwork multicast:RACReplaySubject.subject] autoconnect]; RACSignal* derivedData = [data1FromNetworkHub flattenMap:...]; RACSignal* data2FromNetwork = ...; RACSignal* result = [RACSignal combineLatest:@[data1FromNetworkHub, derivedData, data2FromNetwork]...
ios,objective-c,reactive-cocoa
Okay, two things: You can use the and helper of RACSignal to make that signal reduction a little cleaner: RACSignal *signUpActiveSignal = [[RACSignal combineLatest:@[validEmailSignal, validPasswordSignal, validConfirmPasswordSignal]] and]; You can also use the RAC macro to bind the enabled property (the only reason that the example code is using subscribeNext instead...
key-value-observing,reactive-cocoa
The last paragraph in your question is the key to the solution: What I want to happen is I would get a next event from initializing model.subModels to an empty array... So we'll have one signal watching the subModels property on model. one from adding a sub model to the...
ios,objective-c,key-value-observing,reactive-cocoa,kvc
You can try Method Swizzling, ex: http://nshipster.com/method-swizzling/. To hook whether your set method be called. You can use KVC or Delegate to notify the changing. You can use immutable object to make sure your object is not changed, then hook when it's created. ...
I've just found what was the problem. The local signal used the same thread where it was created and called on: RACSignal *localSignal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) { NSLog(@"Perfoming local operation"); [subscriber sendNext:@"local value"]; [subscriber sendCompleted]; return nil; }]; As I see the problem (I am not sure for...
Just noticed you asked this on SO. I posted a reply on the GitHub repo, but for posterity I'll post my answer here too: @weakify( self ) [[[[[[self findLocation] doError:^( NSError *error ) { @strongify( self ) // There was an error fetching the location so we ask // the...
objective-c,cocoapods,reactive-cocoa
I typically fork the repo, add the podspec and then make changes, here is an example. It looks like: pod 'ReactiveCocoa', :git => "https://github.com/ashfurrow/ReactiveCocoa", :branch => "podspec"...
ios,objective-c,design-patterns,reactive-cocoa,overcoat
You can create SSKeychain category: @interface SSKeychain (RACExtension) - (RACSignal*)rac_setPassword:(NSString *)password forService:(NSString *)serviceName account:(NSString *)account; @end @implementation SSKeychain (RACExtension) - (RACSignal*)rac_setPassword:(NSString *)password forService:(NSString *)serviceName account:(NSString *)account { [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) { NSError *error; BOOL result = [SSKeychain setPassword:password forService:service account:account...
ios,objective-c,reactive-cocoa
Here is an example, it's probably not the best, but I think it worth noting. I use "lift" a lot to remove references to self (and therefore weakify/strongify) ... I played around with your code and got something like this working: - (void)viewDidLoad { [super viewDidLoad]; // Do any additional...
Mark the property as dynamic, and make sure the view model inherits NSObject. class MyViewModel: NSObject { dynamic var amount: NSDecimalNumber } ...
There's a few issues in your code that your own answer has covered, but the reason that you're not getting a next signal is that you're not setting the string by using self.string, instead you're directly accessing the class' variable as _string. Properties are actually Objective-C methods that are cleverly...
There are problem solutions for which ReactiveCocoa is not directly well-suited. I say "directly", because I've found that there is often plenty of opportunity to use RAC near the solution (often by wrapping it), even if it doesn't make sense to use RAC within the solution. Your situation is somewhat...
objective-c,nsuserdefaults,uiswitch,reactive-cocoa
You can bind them (two-way binding) by following: RACChannelTerminal *switchTerminal = self.someSwitch.rac_newOnChannel; RACChannelTerminal *defaultsTerminal = [[NSUserDefaults standardUserDefaults] rac_channelTerminalForKey:@"someBoolKey"]; [switchTerminal subscribe:defaultsTerminal]; [defaultsTerminal subscribe:switchTerminal]; The switch's on state starts with the value from the user defaults or NO....
ios,objective-c,xcode,reactive-cocoa
As from documenation - RACChanelTo - is just a macro, which you can rewrite as [[RACKVOChannel alloc] initWithTarget:<#(NSObject *)#> keyPath:<#(NSString *)#> nilValue:<#(id)#>] So, instead of using RACChanelTo(,) use RACCHannelTerminal *modelTerminal = [[RACKVOChannel alloc] initWithTarget:self keyPath:@"DYNAMIC PROPERTY NAME" nilValue:nil]; WARNING From Reactive Cocoa header /// Do not use this directly. Use...
ios,objective-c,reactive-cocoa
You could monitor reachability, but it's infamously fraught with races and edge cases. It seems like you'd be much better served by catching the errors that from from not being able to complete the network call, or timing out the network call.
ios,objective-c,iphone,mvvm,reactive-cocoa
You are looking for map instead of filter: return [RACObserve(self, selectedLanguage) map:^id(NSString *value){ ... }]; Additional suggestions Also, having side affects (setting self.selectedLanguageAbbreviation) inside the signals is not very good practice and should be avoided if possible. You could change your logic like this: Explicitly bind values of selectedLanguageAbbreviation to...
ios,objective-c,reactive-cocoa
I haven't confirmed this, but here's a possible explanation: Cell X gets called into use, starts downloading an image. Cell X scrolls offscreen before the image download has completed. Cell X gets reused, prepareForReuse is called. Cell X's rac_prepareForReuseSignal sends a value. Because of deliverTo:, the value is dispatched to...
ios,swift,reactive-cocoa,reactive-cocoa-3
You can use the mapError operator. Something along the lines of: self.fooSignalProducer |> mapError { _ in NSError() } Edit: As Justin points out below, promoteErrors is specifically designed for this case: self.fooSignalProducer |> promoteErrors(NSError) ...
ios,objective-c,reactive-cocoa,afhttprequestoperation
For your original question about the jumping download progress, the problem is you're creating subscriptions to two copies of the signal, which is resulting in two downloads. Namely, this bit of code: [[[DownloadMapFileOperation sharedInstance] signalForDownloadMap:self.place] subscribeNext:^(AFHTTPRequestOperation *operation) { NSString *alertMessage = @"Download complete"; [[[UIAlertView alloc] initWithTitle:@"Complete" message:alertMessage delegate:self cancelButtonTitle:@"Close" otherButtonTitles:...
ios,objective-c,mvvm,reactive-cocoa
As described in this answer: you can take rac_textSignal from the text field and use map to trim the string to the desired length. Then bind the mapped signal to the text field using RAC macro. As you noted, view model shouldn't have a reference to the view. But it...
Actually is very good approach to solve this problem with ReactiveCocoa. You want to get the text while the user is typing or in 'Reactive' word you want “Stream” of input text, If your user is a fast typer you want to perform request to server only if the search...
ios,objective-c,mvvm,reactive-cocoa
[RACObserve(self, thresholdLimitReached) filter:^BOOL(id value) { @strongify(self); return self.thresholdLimitReached; }]; You're filtering thresholdLimitReachedSignal so that it only ever returns YES, so your button is always going to be enabled. For starters, you could rewrite that like this and avoid the @weakify/@strongify: [RACObserve(self, thresholdLimitReached) filter:^BOOL(NSNumber *thresholdLimitReached) { return thresholdLimitReached.boolValue; }]; But don't...
objective-c,reactive-programming,reactive-cocoa
The code looks incorrect. You are correct in understanding that the code takes the signal of button taps and maps it to a signal of "sign-in signals". Yes, a signal of signals. While a signal of signals is common and very useful, it will do nothing without the use of...
All rac_keywordify does is allow the use of the @ symbol as a required prefix in front of the weakify and strongify macros. The @ is not necessary, it's a style choice to make those macros look like keywords, like other language keywords, like @try or @synchronize.
ios,objective-c,reactive-cocoa
FWIW, I simplified my code to this and somewhat happy with the results. I'm leaving it here for future reference. - (RACSignal *)loginWithEmail:(NSString *)email password:(NSString *)password { @weakify(self); RACSignal *authSignal = [[self requestTokensWithUsername:email password:password] doNext:^(Authentication *auth) { @strongify(self); self.authentication = auth; }]; RACSignal *profileSignal = [self fetchProfile]; RACSignal *historySignal =...
ios,swift,reactive-cocoa,reactive-cocoa-3
You can use catch() operator for that case like: let producer = ctaTopButton.rac_signalForControlEvents(.TouchUpInside).toSignalProducer() |> map { value in !self.model.enabled.value } |> catch { _ in SignalProducer<Bool, NoError>.empty } ...
swift,mvvm,reactive-cocoa,reactive-cocoa-3
MutablePropertys should be used more like properties, and not as a proxy to a signal. So it should be initialized with a sensible initial value so that anyone that observes it via the producer will get values that make sense. If you want a Signal, you can set up the...
objective-c,mvvm,reactive-cocoa
1) Well, let's look at the signal: RACObserve(self.viewModel, items) When will that complete? Only when self.viewModel or self is deallocated, just like any other RACObserve. As long as those objects are around, it'll keep on nexting any time you set self.items. It appears that you want it to endRefreshing once...
ReactiveCocoa, like all Reactive Extensions-based frameworks, is designed around a push-based API for operating on a series of values. That is, you have some source of values and then you use signal composition to react to the arrival of new values. On the other hand, the "data source" pattern common...
ios,objective-c,reactive-programming,reactive-cocoa
For cases where the code is in the same scope, you could go about this in by using a RACSubject to share the signal, or by using a RACMulticastConnection. Using a RACSubject, it would look like: RACSubject *webAPISubject = [RACSubject subject]; [webAPISubject subscribeNext:^(RACTuple *tuple) { @strongify(self) NSArray *foo = tuple.first;...
You could map to blocks instead of values, NSNumber * (^nextTrack)(NSNumber *) = ^(NSNumber *currentTrack) { return @(currentTrack.integerValue + 1); }; NSNumber * (^previousTrack)(NSNumber *) = ^(NSNumber *currentTrack) { return @(currentTrack.integerValue - 1); }; Now -mapReplace: to those instead of @1/@-1. For track selection, -map: (or here -reduceEach:) the signal...
ios,objective-c,mvvm,reactive-cocoa
For assembling the array of devices, check out -scanWithStart:reduce:. With this method, you could start with an empty array, and have the reduce block add each device to the array. For example: [[[self.browser rac_newDeviceSignal] map:^(RACTuple *parameters) { SDDevice *device = parameters.last; return [[DeviceViewModel alloc] initWithDevice:device]; }] scanWithStart:@[] reduce:^(NSArray models, DeviceViewModel...
It's actually unrelated to the fact that the signal has already completed. Consider this: RACSubject *subject = [RACSubject subject]; [subject finally:^{ NSLog(@"never called"); }]; [subject subscribeCompleted:^{ NSLog(@"called"); }]; [subject sendCompleted]; Still never called! Why? Because finally: returns a new signal; it doesn't modify the existing signal. The new signal will...
You can use catch: for that purpose. [[[[self.registerButton rac_signalForControlEvents:UIControlEventTouchUpInside] doNext:^(id x) { [MBProgressHUD showHUDAddedTo:self.view animated:YES]; self.registerButton.enabled = NO; }] flattenMap:^RACStream *(id value) { Login *login = [Login new]; return [[login registerSignalWithName:self.usernameTextField.text andPassword:self.passwordTextField.text] catch:^RACSignal *(NSError *error) { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error" message:error.localizedDescription...
There is a method for that, distinctUntilChanged: [[[RACObserve(self, self.testProperty) skip:1] distinctUntilChanged] subscribeNext:^(id x) { NSLog(@"Did Change: %@", x); }]; ...
swift,reactive-cocoa,reactive-cocoa-3
So, after writing this question Colin Eberhardt made a part 3 of his RAC3 blog post series which includes a interesting and very relevant example of using MVVM and RAC3. The post can be found here and the source code here. Based on his work, I've managed to answer my...
The flag property could be replaced with an empty method. The implementation of -setupHeartBeat could then use -rac_signalForSelector: on the empty method, instead of RACObserve on the flag. Calling the empty method would be semantically the same as assigning YES to the flag. - (void)resetHeartBeat { } - (RACSignal *)sendRequest:(id)request...
It turned out my Api.get() function should return a SignalProducer instead of a Signal. With this adjustment I ended up with a solution like this: let keywordToJson: SignalProducer<String, NSError> -> SignalProducer<JSON, NSError> = flatMap(.Concat) { keyword in Api().get("search/\(keyword)" } searchText.producer |> mapError { _ in NSError() } |> keywordToJson |>...
ios,objective-c,mvvm,reactive-cocoa
If I'm not misunderstanding you, then the functionality should be easily achievable with combineLatest:reduce:, like so: RACSignal * enabledSignal = [RACSignal combineLatest:@[internetEnabledSignal, executingRegistrationSignal] reduce:^id(NSNumber * internetEnabled, NSNumber * isExecuting) { return @(internetEnabled.boolValue && !isExecuting.boolValue); }].distinctUntilChanged; RAC(self.button, enabled) = enabledSignal; combineLatest:reduce: won't send any next events until all signals have fired...
ios,objective-c,reactive-programming,reactive-cocoa
Check out -flattenMap:. For example: [[inputChanged flattenMap:^(id _) { @strongify(self); return [self asyncWebAPI]; }] subscribeNext:^(id x) { // Do stuff }]; ...
ios,objective-c,timer,reactive-cocoa
I think the missing piece of the puzzle is the very useful flattenMap operator. It essentially replaces any nexts from its incoming signal with nexts from the signal returned by it. Here's one approach to solving your problem (I replaced your newPaymentSignal method with a simple signal sending a string):...
Subscription always happens on a scheduler. If the subscription happens on a thread that has a scheduler, such as the main thread, then that block is executed immediately. If it's not immediate, it means the subscription is being trigger from a thread that doesn't have an associated scheduler. To ensure...