如何使用ReactiveCocoa替换用于管理缓存和网络数据的信号

时间:2015-03-16 09:46:11

标签: ios objective-c caching reactive-programming reactive-cocoa

我正在尝试实现类似于https://github.com/ReactiveCocoa/ReactiveCocoa/issues/1176所讨论的内容,其中缓存管理器返回信号,然后在刷新数据时网络返回新信号。

当您实际处理已保存在缓存中并且必须从网络刷新的数据时,此方法可以正常工作。

然后我添加了数据分页(服务器实际上返回给定索引的数据页面和每页的项目数)。 现在发生的事情是我需要区分我得到的信号是来自缓存还是网络,因为我需要知道是否应该将结果连接到UI中显示的项目数组,或者我是否应该更换其中一些来自网络信号。

起初我以为我可以在模型中添加一个标志,告诉它是缓存响应还是网络响应。但也许RactiveCocoa内置了一些东西,以更好的方式满足我的需求。

这是我提出的同时代码。 这部分是被称为加载数据的部分。它首先询问缓存然后触发网络信号。每次网络调用后,缓存也会被刷新(缓存是一个SQLite数据库,我存储请求路径,请求参数和响应体)

- (RACSignal *)getRanking:(NSString *)typeRanking userId:(NSString *)userId skip:(NSInteger)skip take:(NSInteger)take {
    NSParameterAssert(typeRanking != nil);
    NSParameterAssert(userId != nil);
    NSParameterAssert(skip >= 0);
    NSParameterAssert(take > 0);
    NSMutableDictionary *options = [NSMutableDictionary dictionary];
    options[@"typeRanking"] = typeRanking;
    options[@"IdUser"] = userId;
    options[@"skip"] = [NSNumber numberWithInteger:skip];
    options[@"take"] = [NSNumber numberWithInteger:take];
    NSURLRequest *request = [self requestWithMethod:@"GET" path:@"/api/ranking/GetRanking" parameters:options];
    RACSignal *cachedSignal = [[ALTCacheManager sharedInstance] fetchCachedData:request];
    cachedSignal = [cachedSignal flattenMap:^RACStream *(id value) {
        NSLog(@"%@", value);
        return [self parsedResponseOfClass:ALTRankingResponse.class fromJSON:value];
    }];
    RACSignal *networkSignal =  [[self enqueueRequest:request resultClass:ALTRankingResponse.class cacheResponse:YES] alt_parsedResults];
    return [cachedSignal takeUntilReplacement:networkSignal];
}

我的ViewModel只是以下代码:

@interface ALTChartViewModel ()

@property (nonatomic, strong) ALTRankingModel *rankingModel;
@property (nonatomic, strong) NSArray *rankingPositions;
@property (nonatomic) NSInteger rowsForLastBatch;
@end

@implementation ALTChartViewModel

-(instancetype)init {
    self = [super init];
    if (!self) return nil;

    self.rankingPositions = [NSArray array];
    self.rowsForLastBatch = -1;

    return self;
}

- (RACSignal *) loadRanking:(NSString *)typeRanking skip:(NSInteger)skip take:(NSInteger)take {
    if (self.rowsForLastBatch == 0) return [RACSignal empty];
    RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        [[[ALTWSClient sharedInstance] getRanking:typeRanking userId:@"" skip:skip take:take] subscribeNext:^(ALTRankingResponse *response) {
            self.rankingModel = response.dataObject;
            self.rankingPositions = [self.rankingPositions arrayByAddingObjectsFromArray:self.rankingModel.ranking];
            self.rowsForLastBatch = self.rankingModel.ranking.count;
            [subscriber sendNext:nil];
            [subscriber sendCompleted];
        }];
        return nil;
    }];
    return signal;
}



@end

现在发生的事情是首先将缓存的数据添加到rankingPositions数组,然后将网络数据添加到同一个数组中。相反,我想根据收到的信号类型添加或替换数组的大块。

也许我只是过度思考所有这些并且我应该检查返回的每一行,并根据我已经在那里或不在那里的事实在我的阵列中添加或替换它(它&#39; s有序的数据,只需通过查看位置即可完成。

0 个答案:

没有答案