在ReactiveCocoa中切换UIButton中视图的可见性

时间:2014-06-12 23:03:09

标签: ios objective-c reactive-cocoa

我的视图中有一个按钮,可以动画显示另一个视图。菜单按钮可以显示和隐藏菜单的方式相同。这就是我现在所拥有的:

- (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;
}

这个问题是它迫使我在self.menuView.isShowing中存储状态。我很确定这不是正确的做法。如何改变这一点,以便按钮在隐藏和显示菜单之间交替,而不存储状态?

编辑: 好吧,我最好的猜测是创建单独的命令来显示和隐藏菜单,然后每次都将另一个命令设置为副作用。很想听到任何更好的想法!

2 个答案:

答案 0 :(得分:3)

这是一个例子,它可能不是最好的,但我认为值得注意。我使用“lift”来删除对self的引用(因此弱化/强化)...我玩了你的代码并得到了类似的东西:

- (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];
}

我不确定是否有任何需要解释。实质上,由于每当changeVisibility信号触发时都会有rac_liftSelector的行,所以广播的消息(对象)将被传递给setMenuVisibility方法。值得注意的是,所有NSNumber的东西都与我们无法传递BOOL的事实有关,因为它不是一个对象。

我自己还在学习这些东西,但我希望有所帮助。

答案 1 :(得分:3)

以下是使用RACCommand返回值和RAC宏的组合的更短且更惯用的版本:

@weakify(self);
RACCommand *toggleMenuCommand = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
    @strongify(self);
    return [RACSignal return:@(!self.menuView.hidden)];
}];

self.myButton.rac_command = toggleMenuCommand;

RAC(self.menuView, hidden) = [[toggleMenuCommand executionSignals] flatten];

请注意,[toggleMenuCommand executionSignals]会返回信号信号,这就是为什么需要flatten