ReactiveCocoa基于NSTableView选择状态启用NSButton

jps*_*asi 4 cocoa objective-c reactive-cocoa

我刚开始学习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];
Run Code Online (Sandbox Code Playgroud)

此代码执行正常并在应用程序启动期间禁用了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];
        }
    }
}];
Run Code Online (Sandbox Code Playgroud)

我们赞赏任何建议以反应方式处理要求.

谢谢

Jos*_*ell 8

你走在正确的轨道上.您应该进行一些简化以进行简化.

首先,使用RAC()宏来对属性执行这样的简单绑定.

RAC(self.addButton, enabled) = /* A signal */;
Run Code Online (Sandbox Code Playgroud)

这将导致编译错误,因为没有声明的属性enabled(并且getter被命名isEnabled,而不仅仅是`enabled).这可以通过以下类别非常简单地修复:

@interface NSButton (EnabledProp)

@property (assign, nonatomic, getter = isEnabled, setter = setEnabled:) BOOL enabled;

@end
Run Code Online (Sandbox Code Playgroud)

然后,您可以numberOfSelectedRows使用另一个宏直接从表视图构造信号RACObserve().

RAC(self.addButton, enabled) = RACObserve(self.genreListTableView, numberOfSelectedRows);
Run Code Online (Sandbox Code Playgroud)

但这需要成为一种BOOL有意义的约束力.将一种价值转化为另一种价值?那是一个map:.

RAC(self.addButton, enabled) = [RACObserve(self.genreListTableView, numberOfSelectedRows) map:^id (NSNumber * numSelected){
                                          return @([numSelected integerValue] > 0);
}];
Run Code Online (Sandbox Code Playgroud)

NSIntegernumberOfSelectedRows在被包裹起来NSNumber时,它的信号中的,所以解开它,比较到零,然后包裹比较结果备份.

  • 这种事情可以直接使用`RACCommand`来完成.不应该绕过手动更新按钮的"启用"状态.事实上,这样做可能会导致不确定的更新,就像断言试图指出的那样. (2认同)