I have just started learning Reactive Cocoa. I am writing cocoa application where i want to enable the NSButton only if at least one row is selected in NSTableView.
I am using the following code in awakeFromNib
RACSignal *enableSignal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
@strongify(self);
if ([self.genreListTableView numberOfSelectedRows] > 0) {
[subscriber sendNext:@YES];
} else {
[subscriber sendNext:@NO];
}
return nil;
}];
[self.addButton rac_liftSelector:@selector(setEnabled:)
withSignals:enableSignal,nil];
This code executed fine and made the addButton disabled during the app launch as there was no row selected Initially.
I want to make add Button enabled when ever TableView entry is selected. I don't know how to achieve in reactive way.
I could achieve the required behavior in the following manner.Not sure if this is the correct way to achieve it.
[[self rac_signalForSelector:@selector(tableViewSelectionDidChange:)
fromProtocol:@protocol(NSTableViewDelegate)] subscribeNext:^(RACTuple *value) {
NSNotification *notification = value.first;
if (self.genreListTableView == notification.object) {
if ([self.genreListTableView numberOfSelectedRows] > 0) {
[self.addButton setEnabled:TRUE];
} else {
[self.addButton setEnabled:FALSE];
}
}
}];
Any suggestion is appreciated to handle the requirement in reactive way.
Thank you
You're on the right track. There are a few changes you should make to simplify.
First, use the RAC()
macro to do simple bindings like this to a property.
RAC(self.addButton, enabled) = /* A signal */;
This will cause a compilation error because there is no declared property for enabled
(and the getter is named isEnabled
, not just `enabled). This can be fixed very simply with a category:
@interface NSButton (EnabledProp)
@property (assign, nonatomic, getter = isEnabled, setter = setEnabled:) BOOL enabled;
@end
Then, you can construct a signal directly from the table view's numberOfSelectedRows
using another macro, RACObserve()
.
RAC(self.addButton, enabled) = RACObserve(self.genreListTableView, numberOfSelectedRows);
But that needs to be a BOOL
for it to make sense as a binding. Transforming one type of value into another? That's a map:
.
RAC(self.addButton, enabled) = [RACObserve(self.genreListTableView, numberOfSelectedRows) map:^id (NSNumber * numSelected){
return @([numSelected integerValue] > 0);
}];
The NSInteger
from numberOfSelectedRows
is wrapped up in an NSNumber
when it's in the signal, so unwrap it, compare to zero, and then wrap the comparison result back up.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With