ReactiveCocoa相当新,我尝试构建一个信号,从远程API中异步获取某些资源,客户端必须首先对其进行身份验证。通过首先从API获取令牌,然后通过一些自定义HTTP头为每个后续请求传递它来处理身份验证。但是,在订阅fetchResource信号之后,可能会设置自定义标头,这在当前情况下会导致未经身份验证的请求。我想我实际上可以在self.authenticationStatus的subscribeNext块中构建请求,从而确保将设置令牌,但是我怎么能处理信号的处理呢?
- (RACSignal *)fetchResource
{
return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
NSURLRequest *request = [self.requestSerializer
requestWithMethod:@"GET"
URLString:[[NSURL URLWithString:@"resource" relativeToURL:self.baseURL] absoluteString]
parameters:nil error:nil];
NSURLSessionDataTask *task = [self dataTaskWithRequest:request
completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
if (error) {
[subscriber sendError:error];
} else {
[subscriber sendNext:responseObject];
[subscriber sendCompleted];
}
}];
// Actually trigger the request only once the authentication token has been fetched.
[[self.authenticationStatus ignore:@NO] subscribeNext:^(id _) {
[task resume];
}];
return [RACDisposable disposableWithBlock:^{
[task cancel];
}];
}];
}
答案 0 :(得分:2)
- (RACSignal *)fetchTokenWithCredentials:(Credentials *)credentials
{
return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
// Fetch the token and send it to `subscriber`.
Token *t = ... ;
[subscriber sendNext:t];
return nil;
}];
}
- (RACSignal *)fetchResourceWithToken:(Token *)token
{
return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
// Use `token` to set the request header. Then fetch
// the resource and send it to `subscriber`. Basically
// this part is what you already have.
Resource *r = ... ;
[subscriber sendNext:r];
return nil;
}];
}
在视图控制器中,如果您没有有效令牌,则显示模态验证对话框。当用户点击&#34;提交&#34;按钮,执行以下操作:
- (IBAction)handleAuthenticationSubmit:(id)sender
{
Credentials *c = ... ;
RACSignal *resourceSignal = [[[self fetchTokenWithCredentials:c]
flattenMap:^(Token *t) {
return [self fetchResourceWithToken:t];
}]
deliverOn:RACScheduler.mainThreadScheduler];
[self rac_liftSelector:@selector(receiveResource:) withSignals:resourceSignal, nil];
}
- (void)receiveResource:(Resource *)resource
{
[self.delegate authenticationController:self didReceiveResource:resource];
}