我刚开始学习Reactive Cocoa。我正在编写cocoa应用程序,我只想在NSTableView中选择至少一行时启用NSButton。
我在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];
此代码执行正常并在应用启动期间禁用了addButton,因为最初没有选择行。
我希望在选择TableView条目时启用添加按钮。我不知道如何以反应的方式实现。
我可以通过以下方式实现所需的行为。不确定这是否是实现它的正确方法。
[[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];
}
}
}];
我们赞赏任何以反应方式处理要求的建议。
谢谢
答案 0 :(得分:8)
你走在正确的轨道上。您应该进行一些简化以进行简化。
首先,使用RAC()
宏对属性进行简单绑定。
RAC(self.addButton, enabled) = /* A signal */;
这将导致编译错误,因为enabled
没有声明的属性(并且getter被命名为isEnabled
,而不仅仅是`enabled)。这可以通过以下类别轻松修复:
@interface NSButton (EnabledProp)
@property (assign, nonatomic, getter = isEnabled, setter = setEnabled:) BOOL enabled;
@end
然后,您可以使用另一个宏numberOfSelectedRows
直接从表格视图的RACObserve()
构建信号。
RAC(self.addButton, enabled) = RACObserve(self.genreListTableView, numberOfSelectedRows);
但是,它必须是BOOL
才能使它成为一种绑定。将一种价值转化为另一种价值?那是map:
。
RAC(self.addButton, enabled) = [RACObserve(self.genreListTableView, numberOfSelectedRows) map:^id (NSNumber * numSelected){
return @([numSelected integerValue] > 0);
}];
来自NSInteger
的{{1}}在信号中包含在numberOfSelectedRows
中,因此请将其解包,与零比较,然后将比较结果重新打包。
答案 1 :(得分:2)
使用Josh Caswell的方法,您可以按如下方式修改观察结果:
[[[RACObserve(self.genreListTableView, numberOfSelectedRows) distinctUntilChanged] deliverOn:[RACScheduler mainThreadScheduler]] subscribeNext:^(NSNumber* numSelected) {
[self.addButton setEnabled:([numSelected integerValue] > 0)];
}];