在上面的代码中,subscribeNext:block首先获取包含微博的数组。然后linq_select方法对数组中的每个元素执行提供的block,来把NSDictionary的数组转换成RWTweet的数组。
转换完成就把微博发送给result view controller。
构建运行,终于能看到微博展示在UI中了:
注意:ReactiveCocoa 和 LinqToObjectiveC 灵感的来源相似。 ReactiveCocoa以微软的 Reactive Extensions 库为模型,而 LinqToObjectiveC 以 Language Integrated Query APIs或者说 LINQ为模型,特别是 Linq to Objects.
你可能注意到了每条微博的左侧有一段空隙,这是用来显示Twitter用户头像的。
RWTweet类有一个属性profileImageUrl来存放头像的URL。为了让table view能流畅地滚动,你需要让用URL获取图像的代码不在主线程中执行。你可以使用Grand Central Dispatch或者NSOperationQueue来实现。但是为什么不用ReactiveCocoa呢?
打开RWSearchResultsViewController.m,添加下面的方法:
-(RACSignal *)signalForLoadingImage:(NSString *)imageUrl { RACScheduler *scheduler = [RACScheduler schedulerWithPriority:RACSchedulerPriorityBackground]; return [[RACSignal createSignal:^RACDisposable *(id subscriber) { NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:imageUrl]]; UIImage *image = [UIImage imageWithData:data]; [subscriber sendNext:image]; [subscriber sendCompleted]; return nil; }] subscribeOn:scheduler]; }
你现在应该对这个模式已经很熟悉了。
上面的方法首先获取一个后台scheduler,来让signal不在主线程执行。然后,创建一个signal来下载图片数据,当有订阅者时创建一个UIImage。最后是subscribeOn:来确保signal在指定的scheduler上执行。
太神奇了!
现在还是在这个文件中,在tableView:cellForRowAtIndex:方法的return语句之前添加下面的代码:
cell.twitterAvatarView.image = nil; [[[self signalForLoadingImage:tweet.profileImageUrl] deliverOn:[RACScheduler mainThreadScheduler]] subscribeNext:^(UIImage *image) { cell.twitterAvatarView.image = image; }];
因为cell是重用的,可能有脏数据,所以上面的代码首先重置图片。然后创建signal来获取图片数据。你之前也遇到过deliverOn:这一步,它会把next事件发送到主线程,这样subscribeNext:block就能安全执行了。
这么简单真是好。
构建运行,现在头像就能正确地显示出来了: