objective-c - ReactiveCocoa 信号,用于在观察身份验证状态时获取数据

标签 objective-c asynchronous nsurlsession reactive-cocoa racsignal

ReactiveCocoa 相当新,我正在尝试构建一个信号,该信号从客户端必须首先验证的远程 API 异步获取一些资源。身份验证的处理方式是首先从 API 获取 token ,然后通过一些自定义 HTTP header 将其传递给每个后续请求。但是,自定义 header 可能会在订阅 fetchResource 信号后设置,这在当前情况下会导致未经身份验证的请求。我想我实际上可以在 self.authenticationStatus 的 subscribeNext block 中构建请求,从而确保设置 token ,但我该如何处理信号的处理呢?

- (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];
        }];
    }];
}

最佳答案

- (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;

    }];
}

如果您没有有效的 token ,请在您的 View Controller 中显示模态身份验证对话框。当用户点击“提交”按钮时,执行如下操作:

- (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];
}

关于objective-c - ReactiveCocoa 信号,用于在观察身份验证状态时获取数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25473297/

相关文章:

ios - 在 Swift 中实例化带有标识符的 View Controller

javascript - 在 JavaScript 中等待两个异步命令

Javascript 对象和异步调用

ios - NSURLSession - 使用带有 AWS IOS 开发工具包的 uploadTaskWithStreamedRequest

objective-c - NSMutableURLRequest setTimeoutInterval 在 ios 11.0 中不起作用

objective-c - 在 Xcode 中使用 Storyboard,如何在 iOS 中处理大量 Storyboard

objective-c - 设置 UITableView ContentInset

ios - Xcode AMSlideMenu 只用一个按钮打开左侧菜单,禁用滑动

c# - asp.net 核心托管服务中的 "timer + Task.Run"与 "while loop + Task.Delay"

ios - NSMutableURLRequest 的响应不包含信息