请求使用ReactiveCocoa重试网络API调用失败

时间:2015-05-27 05:12:18

标签: ios reactive-cocoa

我在iOS应用中使用ReactiveCocoa来处理网络API请求。如果我想显示UIAlertView并要求用户单击重试按钮并且只在用户单击重试按钮时重试相同的API调用,该怎么办?

- (RACSignal*) fetchImportantData {
    return [RACSignal createSignal: ^RACDisposable*(id<RACSubscriber> subscriber) {
        return [apiCall subscribeNext:^(id x) {
            [subscriber sendNext:x]; 
            [subscriber sendCompleted];
        } error:^(NSError *error) {
            [subscriber sendError:error];
        }];
    }];
}

1 个答案:

答案 0 :(得分:3)

这应该可以解决问题。

RACSignal * catchSignal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
    UIAlertView * alertView = [[UIAlertView alloc]
                               initWithTitle:@"Try again"
                               message:@""
                               delegate:nil
                               cancelButtonTitle:@"No"
                               otherButtonTitles:@"Yes", nil];
    [alertView.rac_buttonClickedSignal subscribeNext:^(NSNumber * buttonIndex) {
        if (buttonIndex.integerValue != alertView.cancelButtonIndex)
        {
            [subscriber sendCompleted];
        }
        else
        {
            [subscriber sendError:nil];
        }
    }];
    [alertView show];
    return nil;
}];

[[[[[self fetchImportantData] catchTo:catchSignal] repeat] take:1] subscribeNext:^(id x) {
    NSLog(@"NEXT: %@", x);
} error:^(NSError *error) {
    NSLog(@"ERROR: %@", error);
} completed:^{
    NSLog(@"COMPLETED");
}];

所以这里发生的是来自fetchImportantData的错误被catchTo:捕获,然后信号被该信号发送的任何内容所取代(它有点像flattenMap:,但是为了错误)。由于我们现在可以控制,我们可以将sendCompleted连接到“是”按钮并使用repeat在完成后重复信号,同时将sendError:连接到“否”按钮这样,如果用户不想重试,我们可以立即停止所有订阅。

fetchImportantData最终返回非错误时,它将被发送并完全跳过我们的catchTo:块,并且感谢我们的take:1信号将完成。