我在链接的操作列表中处理其中一个操作时遇到问题。我尝试使用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方式的任何其他提示也将不胜感激。
答案 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];
}]