某天看到技術羣裏 傳了一份 知乎上的 如何面試 iOS 工程師?的面試題 裏面有一題: 麻煩你設計個簡單的圖片內存緩存器(移除策略是必定要說的)。別的題不敢說,這題 用上篇文章的 ZBNetworking 就能夠作到。 上篇提到 ZBNetworking 優勢1. 低耦合,易擴展。可能有的朋友沒當回事。今天就用 ZBNetworking裏面的ZBCacheManager 類去製做圖片內存緩存器,(準確的說個人緩存是磁盤存儲,並非內存),但我感受出題者就是再問 怎麼設計個簡單圖片緩存器。其實加上內存也很簡單用NSCache 在判斷 存 取時 多加幾個if而已。可是ZBNetworking已經設計時就定位了 磁盤存儲。仍是不改了。git
在咱們開發維護的應用裏 圖片請求已經有很是多的優秀第三方框架了 SDWebImage,YYWebImage 等等 。可是在某個角落仍是能常常看到下面的代碼,一個系統本身的圖片請求方法。製做簡單的圖片緩存器,咱們就用簡單的,若是咱們給這樣的代碼加上緩存,那麼是否是很是👍github
NSURL *url=[NSURL URLWithString:imageUrl];
NSData *data=[NSData dataWithContentsOfURL:url];
UIImage *image=[UIImage imageWithData:data];
複製代碼
先寫一個方法面試
- (void)requestImageUrl:(NSString *)imageUrl completion:(downloadCompletion)completion{
if (!imageUrl)return;
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSURL *url=[NSURL URLWithString:imageUrl];
NSData *data=[NSData dataWithContentsOfURL:url];
UIImage *image=[UIImage imageWithData:data];
dispatch_async(dispatch_get_main_queue(), ^{
completion(image);
});
});
}
複製代碼
一個在子線程 的圖片請求,並在後面有個block回調,返回一個 請求完成的UIimage.下面用ZBCacheManager進行存儲緩存
[self requestImageUrl:imageUrl completion:^(UIImage *image){
[[ZBCacheManager sharedInstance]storeContent:image forKey:imageUrl path:path];
}];
複製代碼
代碼很簡單 當咱們請求完成了 把返回的UIimage進行存儲到指定路徑(要提早建立存儲路徑),bash
- (void)downloadImageUrl:(NSString *)imageUrl path:(NSString *)path completion:(downloadCompletion)completion{
if ([[ZBCacheManager sharedInstance]diskCacheExistsWithKey:imageUrl path:path]) {
[[ZBCacheManager sharedInstance]getCacheDataForKey:imageUrl path:path value:^(NSData *data,NSString *filePath) {
UIImage *image=[UIImage imageWithData:data];
completion(image) ;
}];
}else{
[self requestImageUrl:imageUrl completion:^(UIImage *image){
[[ZBCacheManager sharedInstance]storeContent:image forKey:imageUrl path:path];
completion(image);
}];
}
}
複製代碼
和ZBNetworking 同樣的思路,有緩存就返回緩存,沒緩存就進行請求,並存儲。下面是適配不一樣類型的方法框架
- (void)downloadImageUrl:(NSString *)imageUrl{
[self downloadImageUrl:imageUrl completion:nil];
}
- (void)downloadImageUrl:(NSString *)imageUrl completion:(downloadCompletion)completion{
[self downloadImageUrl:imageUrl path:[self imageFilePath] completion:completion];
}
- (void)downloadImageUrl:(NSString *)imageUrl path:(NSString *)path{
[self downloadImageUrl:imageUrl path:path completion:nil];
}
- (void)downloadImageUrl:(NSString *)imageUrl path:(NSString *)path completion:(downloadCompletion)completion{
if ([[ZBCacheManager sharedInstance]diskCacheExistsWithKey:imageUrl path:path]) {
[[ZBCacheManager sharedInstance]getCacheDataForKey:imageUrl path:path value:^(NSData *data,NSString *filePath) {
UIImage *image=[UIImage imageWithData:data];
completion(image) ;
}];
}else{
[self requestImageUrl:imageUrl completion:^(UIImage *image){
[[ZBCacheManager sharedInstance]storeContent:image forKey:imageUrl path:path];
completion(image);
}];
}
}
//存儲路徑 默認緩存路徑 /Library/Caches/ZBKit/AppImage
- (NSString *)imageFilePath{
NSString *AppImagePath = [[[ZBCacheManager sharedInstance]ZBKitPath]stringByAppendingPathComponent:ImageDefaultPath];
return AppImagePath;
}
複製代碼
多是我的習慣吧,老是喜歡自定義路徑。因此除了能夠存儲到默認路徑,還能夠存到你想存的路徑。async
下面是顯示緩存大小/個數 ,刪除緩存的操做學習
//大小
- (NSUInteger)imageFileSize{
return [[ZBCacheManager sharedInstance]getFileSizeWithpath:[self imageFilePath]];
}
//數量
- (NSUInteger)imageFileCount{
return [[ZBCacheManager sharedInstance]getFileCountWithpath:[self imageFilePath]];
}
//清除圖片
- (void)clearImageFile{
[self clearImageFileCompletion:nil];
}
//清除圖片緩存 有block回調
- (void)clearImageFileCompletion:(ZBCacheCompletedBlock)completion{
[[ZBCacheManager sharedInstance]clearDiskWithpath:[self imageFilePath] completion:completion];
}
//清除某個圖片
- (void)clearImageForkey:(NSString *)key{
[self clearImageForkey:key completion:nil];
}
//清除某個圖片緩存 有block回調
- (void)clearImageForkey:(NSString *)key completion:(ZBCacheCompletedBlock)completion{
[[ZBCacheManager sharedInstance]clearCacheForkey:key path:[self imageFilePath] completion:completion];
}
複製代碼
使用時這樣使用,很簡單易懂ui
self.imageView=[[UIImageView alloc]initWithFrame:CGRectMake(0, 64, SCREEN_WIDTH, 240)];
[self.view addSubview:self.imageView];
//下載圖片
[[ZBWebImageManager sharedInstance] downloadImageUrl:imageUrl completion:^(UIImage *image){
self.imageView.image=image;
}];
複製代碼
- (void)zb_setImageWithURL:(NSString *)urlString{
[self zb_setImageWithURL:urlString completion:nil];
}
- (void)zb_setImageWithURL:(NSString *)urlString placeholderImage:(UIImage *)placeholder{
[self zb_setImageWithURL:urlString placeholderImage:placeholder path:nil];
}
- (void)zb_setImageWithURL:(NSString *)urlString placeholderImage:(UIImage *)placeholder path:(NSString *)path{
[self zb_setImageWithURL:urlString placeholderImage:placeholder path:path completion:nil];
}
- (void)zb_setImageWithURL:(NSString *)urlString completion:(downloadCompletion)completion{
[self zb_setImageWithURL:urlString placeholderImage:nil completion:completion];
}
- (void)zb_setImageWithURL:(NSString *)urlString placeholderImage:(UIImage *)placeholder completion:(downloadCompletion)completion{
[self zb_setImageWithURL:urlString placeholderImage:placeholder path:[[ZBWebImageManager sharedInstance]imageFilePath] completion:completion];
}
- (void)zb_setImageWithURL:(NSString *)urlString placeholderImage:(UIImage *)placeholder path:(NSString *)path completion:(downloadCompletion)completion{
if(placeholder){
self.image=placeholder;
}
__weak __typeof(self)wself = self;
[[ZBWebImageManager sharedInstance]downloadImageUrl:urlString path:path completion:^(UIImage *image){
if (image) {
wself.image=image;
[wself setNeedsLayout];
}else{
wself.image=placeholder;
[wself setNeedsLayout];
}
if (completion) {
completion(image);
}
}];
}
複製代碼
上面核心方法 很簡單的判斷 有佔位圖 先用佔位圖 ,拿到圖片替換佔位圖 。 使用url
[self.imageView zb_setImageWithURL:imageUrl placeholderImage:[UIImage imageNamed:@"zhanweitu"]];
複製代碼
到此 一個簡單圖片緩存器就完事了 可是不能代替其餘第三方,由於圖片還有不少其餘要處理的。就要你們本身慢慢積累了,可是對開始的那個面試題,仍是足夠的。在實際項目中。正如前面所說當咱們遇到這樣的代碼能夠 用一下這個框架 。
NSURL *url=[NSURL URLWithString:imageUrl];
NSData *data=[NSData dataWithContentsOfURL:url];
UIImage *image=[UIImage imageWithData:data];
複製代碼
今後文章能夠感受到ZBNetworking 擴展性好 ZBCacheManager的強大吧,全部的存儲判斷都已經設計好了,只有你在該調用的時候調用就行了。
點擊github地址下載
結尾:水平有限,代碼也很爛,一直在努力學習中,你們多多包涵。若是你喜歡這個輪子,請給個star,這是對做者最大的鼓勵和支持,拜謝!!!假如你有更好的想法或方案請留言!