很多應用在第一次加載時會讀取前一次瀏覽的歷史微博數據,只有當用戶手動觸發下拉刷新之后,才會去加載新的微博數據。
1.集成FMDB
FMDB是在sqlite3的C語言查詢函數基礎上封裝的一套OC的API,因此在使用之前需要首先導入libsqlite3.tbd.
2. 添加FMDB庫
3. 參考代碼:
DJStatusDBHelper.h
#import <Foundation/Foundation.h> @class DJStatus; @interface DJStatusDBHelper : NSObject /** 保存單條微博 */ + (void)saveStatus:(NSDictionary *)statusDictionary; /** 保存多條微博 */ + (void)saveMutableStatus:(NSArray *)statusArray; /** 返回指定個數的微博,默認為20 */ + (NSArray *)statusesWithFixNums; /** 返回比maxId小於或等於的微博 */ + (NSArray *)statusesWithMaxId:(NSString *)max_id; /** 返回比since_Id大的微博 */ + (NSArray *)statusesWithSinceId:(NSString *)since_id; @end
DJStatusDBHelper.m
#import "DJStatusDBHelper.h" #import "FMDatabase.h" #import "DJStatus.h" static FMDatabase *_db; @implementation DJStatusDBHelper // 在這個類第一次被實例化的時候創建數據庫並打開對應的數據表 + (void)initialize { NSString *db_path = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"status.sqlite"]; _db = [FMDatabase databaseWithPath:db_path]; // 1. 打開數據庫 [_db open]; // 2. 創表 NSString *sql = [NSString stringWithFormat:@"CREATE TABLE IF NOT EXISTS t_status(id integer PRIMARY KEY, status blob NOT NULL, idstr text NOT NULL);"]; [_db executeUpdate:sql]; } /** 保存單條微博 */ + (void)saveStatus:(NSDictionary *)statusDictionary { // 這里需要注意,如果要將對象保存到SQLite數據庫,那么這個對象必須轉換為NSData對象,且該對象必須實現NSCoding協議 NSData *statusData = [NSKeyedArchiver archivedDataWithRootObject:statusDictionary]; [_db executeUpdateWithFormat:@"INSERT INTO t_status(status,idstr) VALUES(%@,%@);",statusData,statusDictionary[@"idstr"]]; } /** 保存多條微博 */ + (void)saveMutableStatus:(NSArray *)statusArray { for (int i = 0; i < statusArray.count; i++) { NSDictionary *statusDict = statusArray[i]; [self saveStatus:statusDict]; } } /** 返回指定個數的微博 */ + (NSArray *)statusesWithFixNums { FMResultSet *set = [_db executeQueryWithFormat:@"SELECT * FROM t_status ORDER BY idstr DESC LIMIT 20;"]; NSMutableArray *statusDictArray = [NSMutableArray array]; while (set.next) { NSData *statusData = [set objectForColumnName:@"status"]; NSDictionary *statusDict = [NSKeyedUnarchiver unarchiveObjectWithData:statusData]; [statusDictArray addObject:statusDict]; } return statusDictArray; } /** 返回比since_Id大的微博 */ + (NSArray *)statusesWithSinceId:(NSString *)since_id { FMResultSet *set = [_db executeQueryWithFormat:@"SELECT * FROM t_status WHERE idstr > %@ ORDER BY idstr DESC LIMIT 20;",since_id]; NSMutableArray *statusDictArray = [NSMutableArray array]; while (set.next) { NSData *statusData = [set objectForColumnName:@"status"]; NSDictionary *statusDict = [NSKeyedUnarchiver unarchiveObjectWithData:statusData]; [statusDictArray addObject:statusDict]; } return statusDictArray; } /** 返回比maxId小於或等於的微博 */ + (NSArray *)statusesWithMaxId:(NSString *)max_id { FMResultSet *set = [_db executeQueryWithFormat:@"SELECT * FROM t_status WHERE idstr <= %@ ORDER BY idstr DESC LIMIT 20;",max_id]; NSMutableArray *statusDictArray = [NSMutableArray array]; while (set.next) { NSData *statusData = [set objectForColumnName:@"status"]; NSDictionary *statusDict = [NSKeyedUnarchiver unarchiveObjectWithData:statusData]; [statusDictArray addObject:statusDict]; } return statusDictArray; } @end
DJHomeViewController.m
- (void)pullToRefresh:(MJRefreshHeader *)header { // 判斷是否是第一次刷新。根據statusFrame是否有值,如果有,則代表已經加載過數據;若沒有,則代表首次加載 if (self.statusFrames.count) { [self loadRefreshStatusesFromNetwork:header]; } else { // 嘗試從數據庫中加載數據 [self loadRefreshStatusesFromDatabase:header]; } } /** 嘗試從數據庫中加載數據 */ - (void)loadRefreshStatusesFromDatabase:(MJRefreshHeader *)header { DJLog(@"下拉刷新--從數據庫"); NSArray *statuses = [DJStatusDBHelper statusesWithFixNums]; if (statuses.count) { // 1. 將刷新獲取到的新數據添加到總數組的頭部 NSArray *newStatuses = [DJStatus mj_objectArrayWithKeyValuesArray:statuses]; NSArray *newStatusFrames = [self statusFramesWithStatus:newStatuses]; NSRange range = NSMakeRange(0, newStatusFrames.count); NSIndexSet *indexSet = [[NSIndexSet alloc] initWithIndexesInRange:range]; [self.statusFrames insertObjects:newStatusFrames atIndexes:indexSet]; // 2. 刷新TableView [self.tableView reloadData]; // 3. 結束刷新 [header endRefreshing]; // 4. 清除未讀微博數量 [self clearAllBadgeTips]; // 5. 提示當前刷新微博數量 [self showRefreshStatusesNums:newStatusFrames.count]; } else { DJLog(@"下拉刷新--數據庫沒有,切換到網絡"); // 嘗試從網絡上加載數據 [self loadRefreshStatusesFromNetwork:header]; } } /** 嘗試從網絡上加載數據*/ - (void)loadRefreshStatusesFromNetwork:(MJRefreshHeader *)header { DJLog(@"下拉刷新--從網絡"); AFHTTPSessionManager *requestManager = [AFHTTPSessionManager manager]; NSString *urlString = @"https://api.weibo.com/2/statuses/friends_timeline.json"; NSMutableDictionary *params = [NSMutableDictionary dictionary]; params[@"access_token"] = [DJAccountTool account].access_token; DJStatusCellFrame *statusFrame = [self.statusFrames firstObject]; if (statusFrame) { params[@"since_id"] = statusFrame.status.idstr; } [requestManager GET:urlString parameters:params progress:nil success:^(NSURLSessionDataTask * _Nonnull task, NSDictionary * _Nullable responseObject) { // DJLog(@"%@",responseObject); // 0. 將刷新獲取到的數據先添加到數據庫 [DJStatusDBHelper saveMutableStatus:responseObject[@"statuses"]]; // 1. 將刷新獲取到的新數據添加到總數組的頭部 NSArray *newStatuses = [DJStatus mj_objectArrayWithKeyValuesArray:responseObject[@"statuses"]]; NSArray *newStatusFrames = [self statusFramesWithStatus:newStatuses]; NSRange range = NSMakeRange(0, newStatusFrames.count); NSIndexSet *indexSet = [[NSIndexSet alloc] initWithIndexesInRange:range]; [self.statusFrames insertObjects:newStatusFrames atIndexes:indexSet]; // 2. 刷新TableView [self.tableView reloadData]; // 3. 結束刷新 [header endRefreshing]; // 4. 清除未讀微博數量 [self clearAllBadgeTips]; // 5. 提示當前刷新微博數量 [self showRefreshStatusesNums:newStatusFrames.count]; } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { [header endRefreshing]; }]; } /** 下載加載更多 */ - (void)loadMoreStatuses:(MJRefreshFooter *)footer { DJStatusCellFrame *statusFrame = [self.statusFrames lastObject]; if (statusFrame) { long long max_id = [statusFrame.status.idstr longLongValue] - 1; [self loadMoreStatusesFromDatabaseWithMaxId:[NSString stringWithFormat:@"%lld",max_id] footer:footer]; } else { [self loadMoreStatusesFromNetworkWithMaxId:[NSString stringWithFormat:@"%d",0] footer:footer]; } } /** 載入更多數據從數據庫 */ - (void)loadMoreStatusesFromDatabaseWithMaxId:(NSString *)max_id footer:(MJRefreshFooter *)footer{ DJLog(@"加載更多--從數據庫"); NSArray *statuses = [DJStatusDBHelper statusesWithMaxId:max_id]; if (statuses.count) { // 1. 將刷新獲取到的新數據添加到總數組的尾部 NSArray *newStatuses = [DJStatus mj_objectArrayWithKeyValuesArray:statuses]; NSArray *newStatusFrames = [self statusFramesWithStatus:newStatuses]; [self.statusFrames addObjectsFromArray:newStatusFrames]; // 2. 刷新TableView [self.tableView reloadData]; // 3. 結束刷新 [footer endRefreshing]; } else { DJLog(@"加載更多--數據庫沒有,切換到網絡"); // 嘗試從網絡獲取 [self loadMoreStatusesFromNetworkWithMaxId:max_id footer:footer]; } } /** 載入更多數據從網絡 */ - (void)loadMoreStatusesFromNetworkWithMaxId:(NSString *)max_id footer:(MJRefreshFooter *)footer{ DJLog(@"加載更多--從網絡"); AFHTTPSessionManager *requestManager = [AFHTTPSessionManager manager]; NSString *urlString = @"https://api.weibo.com/2/statuses/friends_timeline.json"; NSMutableDictionary *params = [NSMutableDictionary dictionary]; params[@"access_token"] = [DJAccountTool account].access_token; DJStatusCellFrame *statusFrame = [self.statusFrames lastObject]; if (statusFrame) { long long max_id = [statusFrame.status.idstr longLongValue] - 1; params[@"max_id"] = @(max_id); } [requestManager GET:urlString parameters:params progress:nil success:^(NSURLSessionDataTask * _Nonnull task, NSDictionary * _Nullable responseObject) { // 0.將刷新獲取到的數據添加到數據庫 [DJStatusDBHelper saveMutableStatus:responseObject[@"statuses"]]; // 1. 將刷新獲取到的新數據添加到總數組的尾部 NSArray *newStatuses = [DJStatus mj_objectArrayWithKeyValuesArray:responseObject[@"statuses"]]; NSArray *newStatusFrames = [self statusFramesWithStatus:newStatuses]; [self.statusFrames addObjectsFromArray:newStatusFrames]; // 2. 刷新TableView [self.tableView reloadData]; // 3. 結束刷新 [footer endRefreshing]; } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { [footer endRefreshing]; }]; }
最終效果: