在重试之前使用Reactive Cocoa / Inject副作用重试警报

时间:2014-06-24 08:37:57

标签: objective-c reactive-cocoa

我刚刚开始关注Reactive Cocoa,并认为我目前使用的许多应用程序中的场景应该是一个很好的起点。当应用程序启动时,它会在让用户进入应用程序之前检查用户当前是否位于白名单国家/地区。所以完美的顺序应该是这样的:

  1. 使用核心位置检查设备位置。
  2. 使用CLGeocoder对位置进行反向编码。
  3. 将国家/地区代码与白名单进行比较。
  4. 继续加载应用。
  5. 如果(1)失败,我想告知用户必须使用带有单个重试按钮的UIAlertView启用位置服务。而这正是我无法理解这应该如何完成的地方。目前的代码如下:

    @weakify( self )
    [[[[[[self
        findLocation]
        doError:^( NSError *error ) {
            @strongify( self )
            // There was an error fetching the location so we ask
            // the user to enable location services.
            //
            [self askUserToEnableLocationServices];
        }]
        retry] // What do we really retry here? It doesn't seem like it's [self findLocation]
        flattenMap:^RACStream *( CLLocation *newLocation ) {
            @strongify( self )
            return [self reverseGeocodeLocation:newLocation];
        }]
        flattenMap:^RACStream *( NSString *ISOCountryCode ) {
            @strongify( self )
            return [self checkCountryPermissibleSignal:ISOCountryCode];
        }]
        subscribeNext:^( id x ) {
            NSLog( @"Country is valid!" );
        } error:^( NSError *error ) {
            NSLog( @"Error: %@", error );
        }];
    

    有人对此有任何意见吗?我猜我错了retry的工作方式。我也怀疑我对整个流程看起来有点天真。但是我现在已经坚持了几个晚上。还有一些尚未点击的东西。

1 个答案:

答案 0 :(得分:4)

刚刚注意到你问过这个问题。 I posted a reply on the GitHub repo,但对于后代,我也会在这里发布我的答案:

@weakify( self )
[[[[[[self
    findLocation]
    doError:^( NSError *error ) {
        @strongify( self )
        // There was an error fetching the location so we ask
        // the user to enable location services.
        //
        [self askUserToEnableLocationServices];
    }]
    retry] // What do we really retry here? It doesn't seem like it's [self findLocation]

-retry不会再次致电[self findLocation]。相反,它会创建对从[self findLocation]返回的RACSignal对象的新订阅。由于在发送错误时信号如何操作的合同/语义传递了错误,因此原始订阅被处理掉。

请注意,您对-doError:的调用中的代码将与新订阅同时执行,这可能不是您想要的。换句话说,当您向用户显示警报视图时,您同时会在用户有机会采取任何操作之前重新订阅从-findLocation返回的信号。

如果在原始信号上发送错误,您可以使用-catchTo:指定应订阅的替代信号:

@weakify( self )
RACSignal *recover = [RACSignal createSignal:^(id<RACSubscriber> subscriber) {
    @strongify( self );
    [self askTheUserToEnableLocationServices]
    return nil;
}];

[[[[[self
    findLocation]
    catchTo:recover]
    flattenMap:^RACStream *( CLLocation *newLocation ) {
        @strongify( self )
        return [self reverseGeocodeLocation:newLocation];
    }]
    flattenMap:^RACStream *( NSString *ISOCountryCode ) {
        @strongify( self )
        return [self checkCountryPermissibleSignal:ISOCountryCode];
    }]
    subscribeNext:^( id x ) {
        NSLog( @"Country is valid!" );
    } error:^( NSError *error ) {
        NSLog( @"Error: %@", error );
    }];