使用 ReactiveCocoa 在网络 API 调用失败时请求重试
Ask for retry upon a failure of the network API call by using ReactiveCocoa
我在我的 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];
}];
}];
}
这应该可以解决问题。
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
连接到 "Yes" 按钮并使用 repeat
让信号在完成后重复,同时将 sendError:
连接到 "No" 按钮,以便我们可以在用户不想重试时立即停止所有订阅。
当 fetchImportantData
最终 returns 一个非错误时,它将被发送并完全跳过我们的 catchTo:
块,并且信号将完成感谢我们的 take:1
.
我在我的 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];
}];
}];
}
这应该可以解决问题。
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
连接到 "Yes" 按钮并使用 repeat
让信号在完成后重复,同时将 sendError:
连接到 "No" 按钮,以便我们可以在用户不想重试时立即停止所有订阅。
当 fetchImportantData
最终 returns 一个非错误时,它将被发送并完全跳过我们的 catchTo:
块,并且信号将完成感谢我们的 take:1
.