如何使用RACMulticastConnection进行应用程序组件通知

时间:2014-05-19 15:33:58

标签: ios7 reactive-cocoa racsignal

简短版本: 是否可以像NSNotificationCenter一样使用RACMulticastConnection?我的意思是即使对于另一个呼叫[连接连接],保持订阅的块有效吗?

长版: 在不同的订阅者中,我共享对RACMulticastConnection的引用。发起请求的人通过loginRequest!= nil和那些只想听的用户使用loginRequest == nil:

RACMulticastConnection *connection = [self.appModel loginRequest:loginRequest];
[connection connect]; //I initiate the request


[connection.signal subscribeNext:^(RACTuple* responseTuple) {

} error:^(NSError *error) {

} completed:^{

}];

在其他模块中,我只是订阅并倾听:

RACMulticastConnection *connection = [self.appModel loginRequest:nil];
[connection.signal subscribeNext:^(RACTuple* responseTuple) {

} error:^(NSError *error) {

} completed:^{

}];

当我呼叫[连接连接]时;一切正常。订阅者会收到通知。但是如果我想用[连接连接]再次向服务器重复请求;我只是收到了旧回复的成功信号。

基本思路是我想创建一次RACMulticastConnection并与潜在订阅者共享。那些监听传递nil参数的人,发起请求的人传递的不是nil参数并调用[connection connect];但它不会触发 RACSignal createSignal:中定义的块。

当RACMulticastConnection不存在时,仅创建一次RACSignal。 self.loginRequestConnection 是模型的属性。该属性在订阅者的应用程序中共享:

- (RACMulticastConnection*) loginRequest:(LoginRequest*)request {

    self.loginRequest = request;

    if(! self.loginRequestConnection) { // the instance of RACMulticastConnection shared among the subscribers

        @weakify(self);
        RACSignal* networkRequest = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {

            __block Response* blockResponse = nil;

            @strongify(self);

            [_serviceClient login:self.loginRequest success:^(TSNApiResponse *response, TSNError *error) {

                blockResponse = response;
                [subscriber sendNext:RACTuplePack(response, error)];
                [subscriber sendCompleted];

            } failure:^(TSNError *error) {

                [self cleanUpRequestOnError:error subscriber:subscriber blockResponse:blockResponse blockRequest:self.loginRequest];

                [subscriber sendError:error];
            }];

            return [RACDisposable disposableWithBlock:^{

                [_serviceClient cancelRequest:self.loginRequest];
            }];

        }];

        self.loginRequestConnection = [networkRequest multicast:[RACReplaySubject subject]];
    }

    return self.loginRequestConnection;
}

有没有正确的方法如何使连接再次触发RACSignal中的块?谢谢。

1 个答案:

答案 0 :(得分:1)

我使用过FBKVOController。使用FBKVOController完成的代码是使用ReactiveCocoa完成实现的一小部分:

- (void) loginRequest:(TSNLoginRequest*)request {

    [_serviceClient login:request success:^(TSNApiResponse *response, TSNError *error) {

        self.loginResponseTuple = [TSNResponseTuple responseTuple:response error:error];

    } failure:^(TSNError *error) {

        self.loginResponseTuple = [TSNResponseTuple responseTuple:nil error:error];

   }];
}

发出请求:

[self.appModel loginRequest:loginRequest];

观察回应:

[_KVOController observe:self.appModel keyPath:@"loginResponseTuple" options:NSKeyValueObservingOptionNew block:^(TSNStartupScreenViewModel* observer, TSNAppModel* observed, NSDictionary *change) {

    TSNResponseTuple* responseTuple = change[NSKeyValueChangeNewKey];

    @strongify(self);
    if([responseTuple.error isError]) {

        [TSNAppUtilities showError:(TSNError *)(responseTuple.error) completion:^(OHAlertView *alert, NSInteger buttonIndex) {

            if(buttonIndex == alert.firstOtherButtonIndex) {

                // ... process selection
            }
        }];
    } 
}];