某天看到技术群里 传了一份 知乎上的 如何面试 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,这是对做者最大的鼓励和支持,拜谢!!!假如你有更好的想法或方案请留言!