Reactive Cocoa:在操作链中出现switchToLatest问题

时间:2015-07-08 10:25:46

标签: ios objective-c reactive-cocoa

我在链接的操作列表中处理其中一个操作时遇到问题。我尝试使用Reactive Cocoa在用户登录时提供位置流并授予对位置服务的访问权限。

我对Reactive Cocoa和功能性反应式编程的世界一般都很陌生,但这是我迄今为止所做的:

Y

当授权状态更改,启动/停止位置流时,这可以正常工作。但是当注销时,位置流继续提供位置。好像@weakify(self); // signal of BOOL RACSignal *loggedInSignal = [[self loggedInSignal] distinctUntilChanged]; // signal of CLAuthorizationStatus RACSignal *currentStateSignal = [[self currentAuthorizationSignal] distinctUntilChanged]; // defer creation of the location stream signal until subscribed to RACSignal *locationSignal = [RACSignal defer:^RACSignal * { @strongify(self); // To get an uninterrupted stream of locations, just retry the stream if an error occurs return [[self locationsSignal] retry]; }]; RACSignal *locationServicesDisabledSignal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) { @strongify(self); [self locationServicesDisabled]; [subscriber sendCompleted]; return nil; }]; self.disposable = [[[[[[loggedInSignal map:^id(NSNumber *loggedIn) { return [loggedIn boolValue] ? currentStateSignal : [RACSignal empty]; }] switchToLatest] map:^id(NSNumber *currentStatus) { if (CLAuthorizationStatusCanBeginMonitoring([currentStatus intValue])) { return locationSignal; } return locationServicesDisabledSignal; }] switchToLatest] subscribeNext:^(CLLocation *location) { @strongify(self); CLLocationCoordinate2D coord = location.coordinate; [self.output receivedNewLocationWithLatitude:coord.latitude longitude:coord.longitude accuracy:location.horizontalAccuracy timestamp:location.timestamp]; }] asScopedDisposable]; 没有被处理掉,调整授权状态仍会启动/停止流,即使loggedInSignal已将authStateSignal作为其最后一个值返回。

我试过了:

NO

在第二次(previous code as above)... return locationServicesDisabledSignal; }] switchToLatest] takeUntil:[loggedInSignal skip:1]] subscribeNext:^(CLLocation *location) { (etc)... 之后在下次登录/退出后停止该信号,但除了感觉有点&#34; hack-ish&#34;之后,它在1登录后停止了位置流事件/出来,永远不要再开始了。处理这种情况的正确方法是什么?

此外,我觉得我以错误的方式使用switchToLatest。我希望在locationServicesDisabledSignal返回指示位置服务被禁用的状态时调用方法,以便我可以做出相应的反应,但是将方法调用放在authStateSignal块中,这样做不会感觉非常活跃的可可。关于如何做我尝试Reactive Cocoa方式的任何其他提示也将不胜感激。

1 个答案:

答案 0 :(得分:0)

它不适合您的原因是当您返回[RACSignal empty];值时,也不会通过您的链传播,因为[RACSignal empty];不会发送任何下一个事件。所以试试这个:

 // signal of BOOL
RACSignal *loggedInSignal = [[self loggedInSignal] distinctUntilChanged];

// signal of CLAuthorizationStatus
RACSignal *currentStateSignal = [[self currentAuthorizationSignal] distinctUntilChanged];

// defer creation of the location stream signal until subscribed to
RACSignal *locationSignal = [RACSignal defer:^RACSignal *
{
    @strongify(self);
    // To get an uninterrupted stream of locations, just retry the stream if an error occurs
    return [[self locationsSignal] retry];
}];

RACSignal *locationServicesDisabledSignal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber)
{
    @strongify(self);
    [self locationServicesDisabled];
    [subscriber sendCompleted];
    return nil;
}];



self.disposable = [[[RACSignal combineLatest:@[loggedInSignal, currentStateSignal]] flattenMap: ^RACStream * (RACTuple *tuple){
    NSNumber* loggedIn = [tuple first];
    NSNumber* currentStatus = [tuple second];
    if([loggedIn boolValue] && CLAuthorizationStatusCanBeginMonitoring([currentStatus intValue])){
        return locationSignal
    }
    else {
        return locationServicesDisabledSignal
    }
} ]
subscribeNext:^(CLLocation *location)
{
@strongify(self);

CLLocationCoordinate2D coord = location.coordinate;
[self.output receivedNewLocationWithLatitude:coord.latitude
                                   longitude:coord.longitude
                                    accuracy:location.horizontalAccuracy
                                   timestamp:location.timestamp];
}]