使用ReactiveCocoa链接来自对象数组的异步操作

Arn*_*nol 9 objective-c ios reactive-cocoa

我有一个实体数组,我想对实体执行异步操作.应该链接操作并以与阵列中的实体相同的顺序运行.我是RAC的新手.如何在RAC中做到这一点?

Dav*_*Lee 12

首先,您需要一个执行异步操作的包装器方法,它将返回一个信号.假设异步操作操作采用完成块.从它的声音,你不关心值,你想要副作用,在这种情况下信号不发送值,它只是完成.

- (RACSignal *)asyncOperation {
    return [RACSignal createSignal:^RACDisposable * (id<RACSubscriber> subscriber) {
        [self asyncOperationWithCompletion:^{
            [subscriber sendCompleted];
        }];
        return nil; // `nil` means there's no way to cancel.
    }];
}
Run Code Online (Sandbox Code Playgroud)

编辑:感谢Justin Spahr-Summers的评论,这是一个更简单的方法来链接操作:

RACSignal *signal = [RACSignal concat:[array.rac_sequence map:^(id entity) {
    return [entity asyncOperation];
}]];
Run Code Online (Sandbox Code Playgroud)

ReactiveCocoa的+concat:运算符接收一组信号并一次订阅一个信号,等待一个信号在订阅其后继信号之前完成.-rac_sequence这里使用的目的是将实体映射到操作信号.

在这种情况下,使用与下面的初始答案中+concat:-then:链接实现相同的效果.


使用RAC包装器,解决方案是从空信号开始,并通过迭代实体并使用组装操作来构建链-then:.该-then:操作基本上等待上一个操作在开始下一个操作之前完成.

RACSignal *signal = [RACSignal empty];
for (id entity in array) {
    signal = [signal then:^{
        return [entity asyncOperation];
    }];
}

[signal subscribeCompleted:^{
    // At this point, all operations have completed
}];
Run Code Online (Sandbox Code Playgroud)

此时你所拥有的是:

[[[[RACSignal empty]
    then:^{ return [entity1 asyncOperation]; }]
    then:^{ return [entity2 asyncOperation]; }]
    // ...
    then:^{ return [entityN asyncOperation]; }]
Run Code Online (Sandbox Code Playgroud)

ReactiveCocoa提供了有用的文档和非常好的文档标题,这些标题在我刚出现时对我来说非常有价值.

  • 您可以使用`+ concat:`来实现类似的功能,而无需重复应用`-then:`. (3认同)