了解RACSignal错误

时间:2014-03-04 08:03:58

标签: ios objective-c reactive-cocoa

我目前正在ReactiveCocoa中迈出第一步,并且经历了一些陡峭的学习曲线来理解这些原理。

无论如何,这是我已经提出的。

我将NSArray属性绑定到RACSignal,以便能够通过网络对传入的JSON数据做出反应。

- (void)updateRandomUserData 
{
    @weakify(self);
    RAC(self, users) = [[self fetchRandomUserData] doNext:^(NSDictionary *json){
    @strongify(self);
    NSMutableArray *randomUsers = [NSMutableArray array];
        for (NSDictionary *dict in json[@"data"]) {
           BKRandomUser *randomUser = [MTLJSONAdapter modelOfClass:[BKRandomUser class] fromJSONDictionary:dict error:nil];
           [randomUsers addObject:randomUser];
        }

        self.users = randomUsers;
    }];
}

信号创建如下:

- (RACSignal *)fetchRandomUserData
{

    return [[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {

      NSURLRequest *request = [NSURLRequest requestWithURL:url];

      AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
      [subscriber sendNext:JSON];
      } failure:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON, NSError *error) {
        [subscriber sendError:error];
      }];

      [operation start];

      return [RACDisposable disposableWithBlock:^{
          [operation cancel];
      }];

      }] doError:^(NSError *error) {
        NSLog(@"error: %@", [error description]);
    }];

}

现在,当Web服务不提供任何我希望对此做出反应的数据时。现在应用程序崩溃了以下声明,我真的不明白:

  

* 由于未捕获的异常'NSInternalInconsistencyException'而终止应用程序,原因:'从名称收到错误:[[+ createSignal:] -doError:] -doNext:在关键路径“users”的绑定中on :( null)'

我在这里缺少什么?

谢谢!

2 个答案:

答案 0 :(得分:11)

接受的答案将解决问题,但有一种更惯用,更优雅的方式来解决这个问题:

首先,不要使用-doNext:,而是使用-map:将您的JSON转换为用户数组:

RAC(self, users) = [[self fetchRandomUserData] map:^(NSDictionary *json){
    NSMutableArray *randomUsers = [NSMutableArray array];
    for (NSDictionary *dict in json[@"data"]) {
       BKRandomUser *randomUser = [MTLJSONAdapter modelOfClass:[BKRandomUser class] fromJSONDictionary:dict error:nil];
       [randomUsers addObject:randomUser];
    }

    return randomUsers;
}];

然后,要处理错误,您可以使用-catch:

RAC(self, users) = [[[self fetchRandomUserData] map:^(NSDictionary *json){
    NSMutableArray *randomUsers = [NSMutableArray array];
    for (NSDictionary *dict in json[@"data"]) {
       BKRandomUser *randomUser = [MTLJSONAdapter modelOfClass:[BKRandomUser class] fromJSONDictionary:dict error:nil];
       [randomUsers addObject:randomUser];
    }

    return randomUsers;
}] catch:^(NSError *error) {
    return [RACSignal return:@[]];
}];

在此示例中,如果发生错误,我们会捕获它并将其替换为空数组。你可以做任何你想做的事。如果您只想忽略整件事,请将其替换为nil+[RACSignal empty]。或者调用另一个返回RACSignal *的方法。

答案 1 :(得分:-4)

  1. 通过编写RAC(self, users),您意味着要将信号的返回绑定到属性users,但是您没有在信号处理程序中返回任何内容。
  2. 您正在使用doNext,这是对当前信号的注入。您可能想要订阅它而不是注入副作用。
  3. 解:

    如果你想在RAC(self, users)副作用中分配它,你可以删除subscribeNext绑定,所以只需订阅信号即可,例如:

    @weakify(self);
    [[self fetchRandomUserData] subscribeNext:^(NSDictionary *json) {
        @strongify(self);
        NSMutableArray *randomUsers = [NSMutableArray array];
        for (NSDictionary *dict in json[@"data"]) {
            BKRandomUser *randomUser = [MTLJSONAdapter modelOfClass:[BKRandomUser class] fromJSONDictionary:dict error:nil];
            [randomUsers addObject:randomUser];
        }
    
        self.users = randomUsers;
    }];