iOS離線緩存
來自: http://www.youngmeng.com/2016/02/12/iOS離線緩存/
為了節省流量和更好的用戶體驗,目前很多應用都使用本地緩存機制,不需要每次打開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 }
</div>
在SQLiteManager.m中
單例:
// 單例 +(SQLiteManager *)sharedInstance { @synchronized(self) { if (shareObj == nil) { shareObj = [[self alloc] init]; } } return shareObj; }
</div>
數據庫初始化:
// 初始化數據庫 -(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; }
</div>
從數據庫獲取數據:
//從數據庫獲取數據 -(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; }
</div>
保存數據到數據庫:
// 保存數據到數據庫 -(void)saveSteps:(Steps *)step { NSData *data = [NSKeyedArchiver archivedDataWithRootObject:step]; [self.database executeUpdateWithFormat:@"INSERT INTO t_step(step) VALUES (%@);", data]; }
</div>
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); }]; } }
</div>
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];
</div>
清除緩存:
//清除緩存 [[SDImageCache sharedImageCache] clearDisk];
</div>
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]; } }
</div>
如果覺得我寫的可以的話,請給我一個star,非常感謝!:smile::smile:
</div> 本文由用戶 MarMebane 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!