Reactive Cocoa在没有代码重复的情况下拆分信号?

时间:2015-06-26 23:01:35

标签: ios objective-c reactive-programming reactive-cocoa

我正在尝试更改正在调用的选择器上的按钮上的标签。

似乎代码是重复的。有没有办法让我现在在地图之后切换信号并不明显?或没有 ?

[[[pressedStart map:^id(id value) {
    UIButton* button = value;
    BOOL transform = [button.titleLabel.text isEqualToString:@"Start"];
    return [NSNumber numberWithBool:transform];

}] filter:^BOOL(id value) {
    return [value boolValue];
}] subscribeNext:^(id x) {
    self.start.titleLabel.text = @"Stop";
}];

[[[pressedStart map:^id(id value) {
    UIButton* button = value;
    BOOL transform = [button.titleLabel.text isEqualToString:@"Stop"];
    return [NSNumber numberWithBool:transform];
}] filter:^BOOL(id value) {
    return [value boolValue];
}] subscribeNext:^(id x) {
   self.start.titleLabel.text = @"Start";
}];

1 个答案:

答案 0 :(得分:3)

首先,要更改按钮的标题,您必须调用其setTitle:forState:方法。

另请注意,在self块中使用subscribeNext可能会创建一个保留周期(因此会导致内存泄漏)。您可以在this answer中详细了解相关信息。您可以使用@weakify / @strongify宏,或者如答案中所述,使用rac_liftSelectors:withSignals:方法(IMHO似乎更清晰)。

您的代码可以简化,因为您根本不需要分割信号。您可以在map块内使用简单条件,并在按下后返回应该是按钮标题的值。该值将作为结果信号的next值发送。您也可以使用startWith:运算符来设置初始值(我猜它应该是"开始")。

RACSignal *buttonTextSignal = [[pressedStart map:^id(UIButton *buttonPressed) {
    return [buttonPressed.titleLabel.text isEqualToString:@"Start"] ? @"Stop" : @"Start";
}]
startWith:@"Start"];
[self.start rac_liftSelector:@selector(setTitle:forState:) withSignals:buttonTextSignal, [RACSignal return:@(UIControlStateNormal)], nil];

rac_liftSelector:withSignals:做什么?每当signals中的一个发送其next值时,它就会调用selector标识的方法(在本例中为setTitle:forState:)。使用next的{​​{1}}值作为参数调用该方法。所以在我们的情况下,它最初会调用:

signals

如果您想设置一个属性(让我们说[self.startButton setTitle:@"Start" forState:UIControlStateNormal]; ),您可以将其与titleLabel.text宏绑定:

RAC

不幸的是,它只适用于设置属性,在您的情况下,您必须使用两个参数调用方法,这就是您必须使用RAC(self.startButton, titleLabel.text) = buttonTextSignal;的原因。

正如我所说,您可以使用rac_liftSelector:withSignals获得所需的结果:

subscribeNext

但正如您所看到的,您应该特别注意使用@weakify(self); RACSignal *buttonTextSignal = [[[pressedStart map:^id(UIButton *buttonPressed) { return [buttonPressed.titleLabel.text isEqualToString:@"Start"] ? @"Stop" : @"Start"; }] startWith:@"Start"] subscribeNext:^(NSString *title) { @strongify(self); [self.startButton setTitle:title forState:UIControlStateNormal]; }]; @weakify宏来避免保留周期。