【原创】开源中国阅读小记 - 1
可能后续会写几篇关于阅读开源中国客户端源码的一些收获。
1. 预编译文件oschina-Prefix.pch
***-Prefix.pch 该文件可以理解为整个工程的公共头文件,往里添加一些不常变的库或者宏定义,可以提升编译效率。
#ifndef __IPHONE_4_0 #warning "This project uses features only available in iOS SDK 4.0 and later." #endif #ifdef __OBJC__ #import <UIKit/UIKit.h> #import <Foundation/Foundation.h> #import <CoreData/CoreData.h> #import <QuartzCore/QuartzCore.h> //添加的预编译 #import "ASIHTTPRequest.h" #import "ASIFormDataRequest.h" #import "ASIHTTPRequestDelegate.h" #import "ASIHTTPRequestConfig.h" #import "AFXMLRequestOperation.h" # 省略。。 #define api_news_list @"http://www.oschina.net/action/api/news_list" #define api_news_detail # 省略。。 //宏定义 新闻 #define TweetCellIdentifier @"TweetCellIdentifier" #define loadMoreIdentifier @"loadMoreIdentifier" #define NewsCellIdentifier @"NewsCellIdentifier" # 省略。。。 #define MyPortraitCellIdentifier @"MyPortraitCellIdentifier" #define IS_IPHONE_5 ( fabs( ( double )[ [ UIScreen mainScreen ] bounds ].size.height - ( double )568 ) < DBL_EPSILON ) #define loadNext20Tip @"下面 20 项 . . ." #define loadingTip @"正在加载 . . ." #define networkError @"网络无连接" #define noNetworkTip @"网络无连接" //消息通知固定字符串 #define Notification_DetailCommentCount @"Notification_DetailCommentCount" #define Notification_NoticeUpdate @"Notification_NoticeUpdate" #define Notification_TabClick @"Notification_TabClick" //html头部
#define USERAGENT @"OSChina.NET/iOS/5.0" #define AppVersion @"1.7.0" #ifdef DEBUG #define debugLog(...) NSLog(__VA_ARGS__) #define debugMethod() NSLog(@"%s", __func__) #else #define debugLog(...) #define debugMethod() #endif #endif
以上所include的头文件,以及宏定义字符串在后续的objc文件里都能任意使用;但需要注意的是,这里所包含的文件应该是极为稳定的,否则每次都得全部重新编译一次。
2. 下面20项
也就是底部继续载入更多条目的实现。其实也就是oschina用的第三方lib:EGORefreshTableHeaderView,比较老了,没有上拉载入的功能。不过也可以看看自己人肉是怎么实现的。
if ([indexPath row] < [news count]) { return cell; } else { return [[DataSingleton Instance] getLoadMoreCell:tableView andIsLoadOver:isLoadOver andLoadOverString:@"已经加载全部新闻" andLoadingString:(isLoading ? loadingTip : loadNext20Tip) andIsLoading:isLoading]; }
默认每页载入20条,当index <= 19(或者当前载入的总数 - 1)的时候,返回具体的cell,否则,返回loadMoreCell
// 用途:返回一个LoadingCell // LoadingCell就是一个Label+UIActivityIndicatorView(载入中状态出现) - (UITableViewCell *)getLoadMoreCell:(UITableView *)tableView andIsLoadOver:(BOOL)isLoadOver andLoadOverString:(NSString *)loadOverString andLoadingString:(NSString *)loadingString andIsLoading:(BOOL)isLoading { LoadingCell * cell = [tableView dequeueReusableCellWithIdentifier:@"loadingCell"]; // 通常用法,如果cell还没创建过(不能被复用),则从nib中载入 if (!cell) { NSArray *objects = [[NSBundle mainBundle] loadNibNamed:@"LoadingCell" owner:self options:nil]; for (NSObject *o in objects) { if ([o isKindOfClass:[LoadingCell class]]) { cell = (LoadingCell *)o; break; } } } cell.lbl.font = [UIFont boldSystemFontOfSize:21.0]; // isLoadOver表示的是,服务器的记录是否已经被全部读完,而不是本次加载完毕 // loadingString的可能是‘下面20项’或‘正在加载 . . .’ cell.lbl.text = isLoadOver ? loadOverString : loadingString; // 如果是正在加载中,那么展示loading view动画 if (isLoading) { cell.loading.hidden = NO; [cell.loading startAnimating]; } else { cell.loading.hidden = YES; [cell.loading stopAnimating]; } return cell; }
上述代码中,并没有点击该列所需要采取的action,具体的action,其实还是在原来的ViewController中实现:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { [tableView deselectRowAtIndexPath:indexPath animated:YES]; int row = [indexPath row]; if (row >= [news count]) { if (!isLoading) { [self performSelector:@selector(reload:)]; } }
reload就是进行page+1的请求,将当前的allCount + 新增的条目数,同时如果是第一页的话,做cache。
该项目做的cache其实是采用NSUserDefaults的方式,key为detail-#-#,value为xml文本。 下次载入第一页的时候还需要做xml的解析。。。
我以前做过的项目用的采用的是序列化对象+write file的方式,两种方式哪一种性能更优,有待验证。