I have a button in my view, that animates another view in and out. Same way a menu button might show and hide a menu. This is what I have right now:
- (void) declareBindings {
self.myButton.rac_command = self.toggleMenuCommand;
}
- (RACCommand *) toggleMenuCommand {
if (!_toggleMenuCommand) {
@weakify(self);
_toggleMenuCommand = [[RACCommand alloc] initWithEnabled:[RACSignal return:@(YES)] signalBlock:^RACSignal *(id sender) {
@strongify(self);
if (!self.menuView.isShowing) {
[self showMenu];
}else{
[self hideMenu];
}
return [RACSignal empty];
}];
}
return _toggleMenuCommand;
}
The problem with this is it's forcing me to store state in self.menuView.isShowing. I'm pretty sure it isn't the right approach. How can I alter this so that the button alternates between hiding and showing the menu, without storing state?
EDIT: OK, my best guess is creating separate commands for showing and hiding the menu, and then setting the other command as a side effect each time. Would love to hear any better ideas!
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 setup after loading the view, typically from a nib.
_toggleMenuCommand = [[RACCommand alloc] initWithEnabled:[RACSignal return:@(YES)] signalBlock:^RACSignal *(id sender) {
return [RACSignal return:sender];
}];
RACSignal *menuView = [RACSignal return:self.menuView];
RACSignal *buttonToggled = [_toggleMenuCommand.executionSignals flatten];
RACSignal *changeVisibility = [RACSignal combineLatest:@[buttonToggled, menuView] reduce:^NSNumber *(UIView *button, UIView *menuView) {
return [NSNumber numberWithBool:menuView.hidden];
}];
[self rac_liftSelector:@selector(setMenuVisibility:)
withSignalsFromArray:@[changeVisibility]];
self.myButton.rac_command = _toggleMenuCommand;
}
- (void)setMenuVisibility:(NSNumber *)visible {
self.menuView.hidden = ![visible boolValue];
}
I'm not sure if any of this needs explaining. Essentially, due to the line with rac_liftSelector
whenever the changeVisibility signal fires, the message (object) that was broadcast will be passed to the setMenuVisibility
method. It's worth noting that all of the NSNumber stuff has to do with the fact that we can't pass BOOL around, because it's not an object.
I'm still learning this stuff myself, but I hope that helps.