译注:作者在原文评论中针对cell重用的问题更新了代码:
[[[[self signalForLoadingImage:tweet.profileImageUrl] takeUntil:cell.rac_prepareForReuseSignal] deliverOn:[RACScheduler mainThreadScheduler]] subscribeNext:^(UIImage *image) { cell.twitterAvatarView.image = image; }];
你可能注意到了,每次输入一个字,搜索Twitter都会马上执行。如果你输入很快(或者只是一直按着删除键),这可能会造成应用在一秒内执行好几次搜索。这很不理想,原因如下:首先,多次调用Twitter搜索API,但大部分返回结果都没有用。其次,不停地更新界面会让用户分心。
更好的解决方法是,当搜索文本在短时间内,比如说500毫秒,不再变化时,再执行搜索。
你可能也猜到了,用ReactiveCocoa来处理这个问题非常简单!
打开RWSearchFormViewController.m,在viewDidLoad中,在filter之后添加一个throttle步骤:
[[[[[[[self requestAccessToTwitterSignal] then:^RACSignal *{ @strongify(self) return self.searchText.rac_textSignal; }] filter:^BOOL(NSString *text) { @strongify(self) return [self isValidSearchText:text]; }] throttle:0.5] flattenMap:^RACStream *(NSString *text) { @strongify(self) return [self signalForSearchWithText:text]; }] deliverOn:[RACScheduler mainThreadScheduler]] subscribeNext:^(NSDictionary *jsonSearchResult) { NSArray *statuses = jsonSearchResult[@"statuses"]; NSArray *tweets = [statuses linq_select:^id(id tweet) { return [RWTweet tweetWithStatus:tweet]; }]; [self.resultsViewController displayTweets:tweets]; } error:^(NSError *error) { NSLog(@"An error occurred: %@", error); }];
只有当,前一个next事件在指定的时间段内没有被接收到后,throttle操作才会发送next事件。就是这么简单。
构建运行,确认一下当停止输入超过500毫秒后,才会开始搜索。感觉比之前好一些吧?你的用户也会这么想的。
到现在你的Twitter Instant应用已经完成了。放松一下,旋转,跳跃,闭上眼吧~
如果你卡在教程中的某个地方了,可以下载最终的工程(再打开之前别忘记运行pod install)。或者在Github上获取这份代码,每一步的构建运行都有一个commit。
译注:最终工程里的代码和文章中的有一些区别。主要是在requestAccessToTwitterSignal方法。
总结在你准备喝杯咖啡放松一下之前,还是有必要来总结一下应用最终的管道图:
数据流还是挺复杂的,现在这全都用响应式的管道清晰地表现了出来。如果不用响应式的话,你能想象到这个应用会变得多复杂吗?数据流会变得多混乱吗?听起来就很麻烦,还好你不用这么做了。
现在你应该知道ReactiveCocoa有多棒了吧!
最后一点,ReactiveCocoa让使用Model View ViewModel,或者说MVVM设计模式成为可能。MVVM能让应用逻辑和视图逻辑更好地分离。如果你想了解更多的话,就来看下一篇教程吧。
ReactiveCocoa入门教程——第二部分
标签: