合并不同类型的信号

Gra*_*rav 2 reactive-cocoa

我正在创建一个音乐播放器,它将响应用户点击某个表格行,或者使用遥控器上的prev/next按钮.

为了获得表示第一种情况的当前播放曲目的索引的信号,我将其作为抽头行的函数,例如:

RACSignal *didSelectS = [[self rac_signalForSelector:@selector(tableView:didSelectRowAtIndexPath:)] map:...
Run Code Online (Sandbox Code Playgroud)

后一种情况,我使用scanWithStart:reduce:我传入+ 1/-1,这取决于用户按下哪个按钮并根据此返回一个新的绝对索引,例如.

RACSignal *prevS = [[remoteControlSignal filter:^BOOL(UIEvent *event) {
    return event.subtype == UIEventSubtypeRemoteControlPreviousTrack;
}] mapReplace:@-1];

RACSignal *nextS = [... mapReplace:@1];

RACSignal *trackIdxS = [RACSignal merge:@[nextS, prevS]] 
                                 scanWithStart:@0
                                 reduce:^id(NSNumber *running, NSNumber *next) {
                                   return @(running.integerValue + next.integerValue);
                                 }];
Run Code Online (Sandbox Code Playgroud)

我的问题是,我如何将这两者结合起来?一种解决方案是将值包装在一个对象中,这样我在scanWithStart:reduce中就可以区分绝对值或相对值,例如:

RACSignal *currentIndexSignal = [[RACSignal merge:@[didSelectS, prevS, nextS] scanWithStart:@0 reduce:^id(NSNumber *running, id next){
   if ([next isKindOfClass:[PrevNextValueWrapper class]]){
     // next is a wrapped relative value, eg -1/+1
     return @(running.integerValue + next.wrappedNumber.integerValue)
   } else {
     // next is an absolute value
     return next;
   }
}
Run Code Online (Sandbox Code Playgroud)

但isKindOfClass和包装对象感觉不对......

Dav*_*Lee 5

你可以映射到块而不是值,

NSNumber * (^nextTrack)(NSNumber *) = ^(NSNumber *currentTrack) {
    return @(currentTrack.integerValue + 1);
};

NSNumber * (^previousTrack)(NSNumber *) = ^(NSNumber *currentTrack) {
    return @(currentTrack.integerValue - 1);
};
Run Code Online (Sandbox Code Playgroud)

现在-mapReplace:给那些而不是@1/ @-1.

对于轨道选择,-map:(或此处-reduceEach:)忽略轨道参数并返回捕获轨道的块的信号:

reduceEach:^(id tableView, NSIndexPath *indexPath) {
    NSInteger newTrack = indexPath.row;
    return ^(NSNumber *currentTrack) {
        return @(newTrack);  
    };
}
Run Code Online (Sandbox Code Playgroud)

现在,可以合并和扫描这些:

RACSignal *currentIndexSignal = [[RACSignal
    merge:@[didSelectS, prevS, nextS]]
    scanWithStart:@0 reduce:^(NSNumber *running, NSNumber * (^trackChanger)(NSNumber *)) {
        return trackChanger(running);
    }];
Run Code Online (Sandbox Code Playgroud)