標籤:
為了節省流量和更好的使用者體驗,目前很多應用都使用本機快取機制,不需要每次開啟app的時候都載入資料,或者重新向伺服器請求資料,因此可以把每次瀏覽的資料儲存到沙箱中,當下次開啟軟體的時候,首先從沙箱載入緩衝的資料,或者當app未連網的時候,從沙箱中載入之前緩衝的舊資料。
離線資料的方法選擇
- plist檔案
- Document路徑
- 資料庫
由於儲存的是大批量資料,且會不停的重新整理新資料,因此應該選擇資料庫來儲存。使用資料庫可以快速地進行資料的讀取操作。
1.設計思路
如,說明了離線緩衝的流程:
離線緩衝
- 當第一次開啟app的時候,把從伺服器擷取到的資料儲存到沙箱中;
- 當下一次進入app的時候,首先從沙箱中找,如果沙箱中儲存了之前的資料,則顯示沙箱中的資料;
- 如果沒有網路,直接載入儲存到沙箱中的資料。
2.實際應用
樣本
下面使用一個樣本程式來介紹離線緩衝。樣本程式用到的架構有FMDB,SDWebImage,AFNetworking,資料是由彙總資料提供的開放API。
JSON返回樣本
{ "resultcode": "200", "reason": "Success", "result": { "data": [ { "id": "1001", "title": "糖醋小排", "tags": "浙菜;熱菜;兒童;酸甜;快手菜", "imtro": "糖醋小排,我估計愛吃的人太多了,要想做好這道菜,關鍵就是調料汁的配置,老抽不能放的太多,那樣顏色太重, 不好看,調料汁調好後,最好嘗一下,每個人的口味都會不同的,可以適當微調一下哈!", "ingredients": "肋排,500g", "burden": "蔥,適量;白芝麻,適量;鹽,3g;生粉,45g;料酒,30ml;雞蛋,1個;蔥,1小段;薑,3片;老抽,7ml;醋,30ml;白糖,20g;番茄醬,15ml;生抽,15ml;生粉,7g;薑,適量", "albums": [ "http://img.juhe.cn/cookbook/t/1/1001_253951.jpg" ], "steps": [ { "img": "http://img.juhe.cn/cookbook/s/10/1001_40ec58177e146191.jpg", "step": "1.排骨剁小塊,用清水反覆清洗,去掉血水" }, { "img": "http://img.juhe.cn/cookbook/s/10/1001_034906d012e61fcc.jpg", "step": "2.排骨放入容器中,放入醃料,攪拌均勻,醃制5分鐘" }, { "img": "http://img.juhe.cn/cookbook/s/10/1001_b04cddaea2a1a604.jpg", "step": "3.鍋中放適量油,燒至5成熱,倒入排骨,炸至冒青煙時撈出,關火,等油溫降至五成熱時,開火,再次放入排骨,中火炸至焦黃、熟透撈出" }, { "img": "http://img.juhe.cn/cookbook/s/10/1001_56b92264df500f01.jpg", "step": "4.鍋中留少許底油,放入蔥花、薑片爆香" }, { "img": "http://img.juhe.cn/cookbook/s/10/1001_d78c57536a08dc4b.jpg", "step": "5.放入適量炸好的排骨,倒入調料汁,煮至湯汁濃稠時,關火,撒入蔥花、白芝麻點綴即可" } ] } ], "totalNum": 1, "pn": 0, "rn": 1 }, "error_code": 0}
在SQLiteManager.m中
單例:
// 單例+(SQLiteManager *)sharedInstance { @synchronized(self) { if (shareObj == nil) { shareObj = [[self alloc] init]; } } return shareObj;}
資料庫初始化:
// 初始化資料庫-(instancetype)init { if (self = [super init]) { //檔案路徑 NSString *path = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"step.sqlite"]; //初始化資料庫 self.database = [FMDatabase databaseWithPath:path]; //開啟資料庫 [self.database open]; if ([self.database open]) { //將step採用blob類型來儲存 NSString *create = @"CREATE TABLE IF NOT EXISTS t_step(id integer PRIMARY KEY, step blob NOT NULL);"; [self.database executeUpdate:create]; } } return self;}
從資料庫擷取資料:
//從資料庫擷取資料-(NSArray *)stepsFromSqlite { NSString *sql = @"SELECT * FROM t_step"; FMResultSet *set = [self.database executeQuery:sql]; NSMutableArray *steps = [NSMutableArray array]; while (set.next) { NSData *data = [set objectForColumnName:@"step"]; Steps *step = [NSKeyedUnarchiver unarchiveObjectWithData:data]; [steps addObject:step]; } return steps;}
儲存資料到資料庫:
// 儲存資料到資料庫-(void)saveSteps:(Steps *)step { NSData *data = [NSKeyedArchiver archivedDataWithRootObject:step]; [self.database executeUpdateWithFormat:@"INSERT INTO t_step(step) VALUES (%@);", data];}
MenuTableViewController.m中
擷取伺服器資料:
//擷取伺服器資料-(void)getData { AFHTTPSessionManager *session = [[AFHTTPSessionManager alloc] init]; NSString *url = @"http://apis.juhe.cn/cook/queryid"; NSMutableDictionary *params = [NSMutableDictionary dictionary]; params[@"id"] = self.menuID; params[@"key"] = self.appKey; params[@"dtype"] = self.dtype; //從資料庫擷取資料 NSArray *steps = [[SQLiteManager sharedInstance] stepsFromSqlite]; if (steps.count) { self.stepsArray = [NSMutableArray arrayWithArray:steps]; } else { //get請求,從伺服器擷取資料 [session GET:url parameters:params progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { NSDictionary *result = responseObject[@"result"]; NSArray *data = result[@"data"]; for (NSDictionary *dict in data) { Menu *menu = [[Menu alloc] initWithDict:dict]; self.stepsArray = menu.steps; } [self.tableView reloadData]; } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { NSLog(@"error=%@",error); }]; }}
3.清除圖片
如:
清除圖片
SDImageCache中提供了擷取當前緩衝大小和清除緩衝的的方法。
MenuTableViewController.m中
擷取當前緩衝大小:
//位元組大小int byteSize = (int)[SDImageCache sharedImageCache].getSize;//M大小CGFloat cacheSize = byteSize / 1000.0 / 1000.0;UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"清理緩衝" message:[NSString stringWithFormat:@"緩衝大小%.1fM",cacheSize] delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"確定", nil];[alert show];
清除緩衝:
//清除緩衝[[SDImageCache sharedImageCache] clearDisk];
4.檔案操作
使用SDImageCache可以清除圖片的緩衝,但是有些緩衝並不是圖片緩衝,例如使用者臨時看的視頻檔案或mp3檔案,如果想要清除這些檔案,就要使用檔案操作的方法,遍曆沙箱中的Library/Cache檔案夾,自己算出快取檔案夾的大小,把所有快取檔案清除。
註:檔案夾是沒有大小的,只有檔案有大小屬性。
//計算當前檔案夾的大小-(NSInteger)cachesFileSize { //檔案管理者 NSFileManager *mgr = [NSFileManager defaultManager]; //判斷是否為檔案 BOOL dir = NO; BOOL exists = [mgr fileExistsAtPath:self isDirectory:&dir]; if (!exists) return 0;//說明檔案或檔案夾不存在 if (dir) { //self是一個檔案夾 //遍曆caches裡面的內容 -- 直接和間接內容 NSArray *subpaths = [mgr subpathsAtPath:self]; NSInteger totalBytes = 0; //如果self是一個檔案夾,則遍曆該檔案夾下的檔案 for (NSString *subpath in subpaths) { //獲得全路徑 NSString *fullpath = [self stringByAppendingPathComponent:subpath]; BOOL directory = NO; [mgr fileExistsAtPath:fullpath isDirectory:&directory]; if (!directory) { // self不是檔案夾,計算檔案的大小 totalBytes += [[mgr attributesOfItemAtPath:fullpath error:nil][NSFileSize] integerValue]; } } return totalBytes; } else { //self是一個檔案 return [[mgr attributesOfItemAtPath:self error:nil][NSFileSize] integerValue]; }}
文/hrscy(簡書作者)
原文連結:http://www.jianshu.com/p/426c66e46f9e
著作權歸作者所有,轉載請聯絡作者獲得授權,並標註“簡書作者”。
iOS離線緩衝