是否有像发布这样的 ReactiveCocoa 方法,但会将最新值转发给新订阅者?

Posted

技术标签:

【中文标题】是否有像发布这样的 ReactiveCocoa 方法,但会将最新值转发给新订阅者?【英文标题】:Is there a ReactiveCocoa method like publish, but that forwards the latest value to new subscribers? 【发布时间】:2014-02-13 20:43:10 【问题描述】:

我经常使用 ReactiveCocoa 来跟踪一些变量的最新值,比如文本字段中的文本。有时,这些最新值实际上是自己计算的,其方式是多次订阅导致计算发生多次。通常,合并这些计算会显着更有效率。

我想使用的是RACSignal* sharedComputationLatest = complicatedLatestValue.publish.autoconnect,但是当新订阅者订阅共享计算信号时,他们不会被告知最新值。

是否有publish 的变体,某种publishLatest,已经存在并且可以满足我的需要?如果没有,它是否已经存在并在 .Net 的 Rx 中有名称?

更新: 事实证明autoconnect 的语义与我想象的略有不同,即如果订阅者数量变为零然后备份,则不会重新连接。我需要重新连接位,所以我实现了自己的方法(在下面的答案中)。

【问题讨论】:

【参考方案1】:

听起来你想要-replayLast

【讨论】:

您能解释一下基础订阅的生命周期是多少吗?我写了一个测试,看看它是否会在 replayLast 的信号被释放时清除底层主题,但它没有?我正在查看源代码,它似乎......永远存在?它实际上从未处理它吗?这对我的用例来说是完全不可接受的。 在这种情况下,您可以使用-multicast:RACReplaySubject(容量为1),然后使用-autoconnect。这不是默认行为,因为在存在多播的情况下处理非常混乱,而且通常不是消费者想要的。 当重播主题被释放时,它仍然应该被释放,对吧?我向 ReactiveCocoa 提交了一个关于它的错误。修复后,此方法将达到我的需要,因此我将其保留为已接受的答案。【参考方案2】:

这是一个自定义实现(注意:不是线程安全的):

-(RACSignal*) publishLatestAutoreconnect 
    __block int32_t subscriberCount = 0;
    __block RACDisposable* subscription = nil;
    __block RACReplaySubject* publishSubject = nil;

    return [RACSignal createSignal:^RACDisposable*(id<RACSubscriber> subscriber) 
        __block RACDisposable* _subscriberDisposable = nil;

        // auto[re]connect if we had no subscribers
        subscriberCount++;
        if (subscriberCount == 1) 
            publishSubject = [RACReplaySubject replaySubjectWithCapacity:1];
            subscription = [self subscribe:publishSubject];
        

        // forward to subscriber
        _subscriberDisposable = [publishSubject subscribe:subscriber];

        return [RACDisposable disposableWithBlock:^
            // stop forwarding to subscriber
            [_subscriberDisposable dispose];

            // disconnect if we now have no subscribers
            subscriberCount--;
            if (subscriberCount == 0) 
                [subscription dispose];
                subscription = nil;
                publishSubject = nil;
            
        ];
    ];

【讨论】:

请注意,您可以改为:[[signal multicast:[RACReplaySubject replaySubjectWithCapacity:1]] autoconnect]; @joshaber 我刚刚意识到自动连接的语义并不是我想象的那样。我希望 dispose on zeroresubscribe on not zero,但自动连接仅在第一次非零时订阅。我将把方法重命名为 autoreconnect。发现这一点非常有用,因此即使您的建议不起作用,它最终也很有帮助。

以上是关于是否有像发布这样的 ReactiveCocoa 方法,但会将最新值转发给新订阅者?的主要内容,如果未能解决你的问题,请参考以下文章

是否有像 Queue 这样实现 IAsyncEnumerable 的 C# 类?

是否有像 scrollviewDidScroll 这样的 uipickerview 委托方法?

是否有像 TInterfacedObject 这样的非引用计数基类?

是否有像 *** 这样的 Spring Security OpenId 注册?

是否有像 DatePicker 这样的组件来选择字符串值?

是否有像 Elgg 这样的插件可用于 Ruby on Rails?