【问题标题】:Buffer signals before particular signal occurs在特定信号出现之前缓冲信号
【发布时间】:2014-02-22 16:53:40
【问题描述】:

我想知道是否可以累积在特定信号的nexts 之间发生的信号结果。类似于

[[[RACSignal
    combineLatest:@[signal1, signal2, signal3]]
    takeUntil:signal4]
    subscribeNext:^(id x) {
        // ...
    }];

但在第一个 signal4next 之后没有完成。

我正在处理的场景是我有一个viewController1,它呈现viewController2viewController2 允许用户更改object,该object 会影响viewController1 中显示的数据。目前我在viewController2 上公开objectChangedSignal 并从viewController1 收听它。

但是,我想直接从viewController1 接收object 的更改,但前提是它触发了viewWillAppear 信号,并且只有在viewWillDisappearviewController1 之后发生更改。

希望有道理,谢谢。

【问题讨论】:

    标签: objective-c reactive-cocoa


    【解决方案1】:

    缓冲值的一种方法是使用-[RACSignal collect],它将它们收集到一个数组中,直到信号完成:

    [[[RACSignal combineLatest:@[ s1, s2, s3 ]]
        collect]
        takeUntil:s4]
    

    但是,您可能希望在最终信号上单独发送每个值,而不是值数组。您可以使用-[RACSignal flattenMap:] 将这些值变平为最终信号:

    [[[[RACSignal combineLatest:@[ s1, s2, s3 ]]
        collect]
        takeUntil:s4]
        flattenMap:^(NSArray *collected) {
    
            return [[collected rac_sequence] signal];
    
        }]
    

    由于您不希望在s4 之后完成您的信号,您可以在每次s4 发送一个值后使用-repeat 重新订阅。如果您不这样做,-takeUntil: 将导致您的信号在发生这种情况时完成。

    [[[[[RACSignal combineLatest:@[ s1, s2, s3 ]]
        collect]
        takeUntil:s4]
        flattenMap:^(NSArray *collected) {
    
            return [[collected rac_sequence] signal];
    
        }]
        repeat]
    

    请注意,如果任何组合信号是冷信号,重新订阅将导致它们的副作用发生更多次。因此,您可能必须通过多播(或组合信号)将它们转换为热信号:

    RACMulticastConnection *mc = [[RACSignal combineLatest:@[ s1, s2, s3 ]] publish];
    RACDisposable *d = [mc connect];
    [[[mc.signal
        takeUntil:s4]
        flattenMap:^(NSArray *collected) {
    
            return [[collected rac_sequence] signal];
    
        }]
        repeat]
    

    如果您的信号将无限存在,您可能需要明确取消订阅(通过处置 d)。

    (注意,此代码未经测试。)

    【讨论】:

    • 感谢您的广泛回答!但它并没有以我想象的方式真正起作用。很可能是由于任务描述不佳:s1s2s3 不一定会触发。但如果他们这样做了,我只想在s4 被解雇后收到通知。
    • 如果s1s2s3 中的任何一个没有发送值,那么-combineLatest: 将永远不会发送值——它会一直等待,直到收到给它的每个信号在发送值的元组之前发送一个值。 (有一些方法可以解决这个问题,例如使用-startWith:。)听起来-[takeUntil:s4] 也不是你想要的,因为当s4 触发时,这完成信号。也许您想要-skipUntilBlock:-skipWhileBlock:-if:then:else: 操作之一?
    猜你喜欢
    • 2013-02-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多