我在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];
}];
}];
}
答案 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
信号将完成。