【问题标题】:Merging signals of different type合并不同类型的信号
【发布时间】:2014-05-05 18:21:22
【问题描述】:

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

为了在第一种情况下获得表示当前播放曲目索引的信号,我会将其设为被点击行的函数,例如:

RACSignal *didSelectS = [[self rac_signalForSelector:@selector(tableView:didSelectRowAtIndexPath:)] map:...

后一种情况,我会使用 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);
                                 }];

我的问题是,如何将这两者结合起来?一种解决方案是将值包装在一个对象中,以便我在我的 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;
   }
}

但是 isKindOfClass 和被包裹的对象感觉不对...

【问题讨论】:

    标签: reactive-cocoa


    【解决方案1】:

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

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

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

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

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

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

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

    【讨论】:

    • 太棒了!就在我的小巷里,感谢指向 reduceEach: 的指针,我不知道 :-) 谢谢!
    • 太棒了!这是一个很好的解决方案!
    • 很高兴我能帮上忙!此类问题经常通过 RAC 存储库上的 GitHub 问题进行讨论。
    猜你喜欢
    • 1970-01-01
    • 2016-12-27
    • 2011-11-26
    • 1970-01-01
    • 2019-08-12
    • 2021-04-01
    • 1970-01-01
    • 2022-07-29
    • 1970-01-01
    相关资源
    最近更新 更多