已阅读5页,还剩5页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
实现iOS图片等资源文件的热更新化(四): 一个最小化的补丁更新逻辑这么做的意义先交代动机和意义,或许应该成为自己博客的一个标准框架内容之一,不然以后自己需要看着,也不过是一堆干瘪的代码.基本的逻辑图,如上!此处,我就从简!从简的原因有3:补丁更新,状态可以设计的很复杂,就像开头那篇文章提到的那样,但是我感觉没多大必要,至少在我们的App中;我想演示一个相对完整的逻辑,但是又不想耗费太多的时间构建场景;从简后的方案,简单但够用了,至少目前针对我们的项目来说;所以说:这篇文章的意义,其实是在于简化已有的热更新代码,越简单越好维护.基本思路App启动时,判断特定的服务器接口所返回的图片url是否为最新,判断方式就是比对返回值中的md5字段与本地保存的资源的url是否一致;如果图片资源有更新,则下载解压到指定的缓存目录,初步打算以资源文件的md5来划分文件夹,来避免冲突;读取图片时,优先从缓存目录读取,缓存目录不存在再从ipa资源包中读取;下面就一步一步来实现了.App启动时,判断有无最新图片资源此处主要涉及到的可能的技术点:1. 如何用基础的网络类库发送网络请求?先简单封装一个函数来获取,用到了block.block经常用,但到现在都记不太清形式,大都是从其他处copy下,然后改改参数.记不住,也懒得记!- (void)fetchPatchInfo:(NSString *) urlStr completionHandler:(void ()(NSDictionary * patchInfo, NSError * error)completionHandler NSURLSessionConfiguration * defaultConfigObject = NSURLSessionConfiguration defaultSessionConfiguration; NSURLSession * defaultSession = NSURLSession sessionWithConfiguration: defaultConfigObject delegate: self delegateQueue: NSOperationQueue mainQueue; NSURL * url = NSURL URLWithString:urlStr; NSURLSessionDataTask * dataTask = defaultSession dataTaskWithURL:url completionHandler:(NSData * data, NSURLResponse * response, NSError * error) NSDictionary * patchInfo = NSJSONSerialization JSONObjectWithData:data options:0 error:&error; completionHandler(patchInfo, error); ; dataTask resume; 基于block,调用的代码也就很简答了.self fetchPatchInfo: /ios122/ios_assets_hot_update/master/res/patch_04.json completionHandler:(NSDictionary * patchInfo, NSError * error) if ( ! error) NSLog(patchInfo:%, patchInfo); else NSLog(fetchPatchInfo error: %, error); ; 好吧,我承认AFNetworking用习惯了,好久没用原始的网络请求的代码了,有点low,莫怪!2. 如何校验下载的文件的md5值,如果你需要的话?开头那篇文章链接里,有提到.核心,其实是在于下载文件之后,md5值的计算,剩余的就是字符串比较操作了.注意要先引入系统库1#include /* * 获取文件的md5信息. * * param path 文件路径. * * return 文件的md5值. */-(NSString *)mcMd5HashOfPath:(NSString *)path NSFileManager * fileManager = NSFileManager defaultManager; / 确保文件存在. if( fileManager fileExistsAtPath:path isDirectory:nil ) NSData * data = NSData dataWithContentsOfFile:path; unsigned char digestCC_MD5_DIGEST_LENGTH; CC_MD5( data.bytes, (CC_LONG)data.length, digest ); NSMutableString * output = NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2; for( int i = 0; i CC_MD5_DIGEST_LENGTH; i+ ) output appendFormat:%02x, digesti; return output; else return ; 3. 使用什么保存与获取本地缓存资源的md5等信息?好吧,我打算直接使用用户配置文件,NSString * source_patch_key = SOURCE_PATCH; NSUserDefaults standardUserDefaults setObject:patchInfo forKey: source_patch_key;patchInfo = NSUserDefaults standardUserDefaults objectForKey: source_patch_key; NSLog(patchInfo:%, patchInfo); 补丁下载与解压此处主要涉及到的可能的技术点:1. 如何基于图片缓存信息来找到指定的缓存目录?问题本身有些绕口,其实我想做的就是根据补丁的md5,放到不同的缓存文件夹,如补丁md5为 e963ed645c50a004697530fa596f180b,则对应放到 patch/e963ed645c50a004697530fa596f180b 文件夹.封装一个简单的根据md5返回缓存路径的方法吧:- (NSString *)cachePathFor:(NSString * )patchMd5 NSArray * LibraryPaths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES); NSString * cachePath = LibraryPaths objectAtIndex:0 stringByAppendingFormat:/Caches/patch stringByAppendingPathComponent:patchMd5; return cachePath; 使用时,类似这样:NSString * urlStr = patchInfo objectForKey: url; weak_self downloadFileFrom:urlStr completionHandler:(NSURL * location, NSError * error) if (error) NSLog(download file url:% error: %, urlStr, error); return; NSString * cachePath = weak_self cachePathFor: patchInfo objectForKey:md5; NSLog(location:% cachePath:%,location, cachePath); ; 2. 如何解压文件到指定目录?如果需要安装 CocoaPods ,建议使用 brew:1brew install CocoaPods 解压本身推荐 SSZipArchive 库,一行代码搞定:1SSZipArchive unzipFileAtPath:location.path toDestination: patchCachePath overwrite:YES password:nil error:&error; 3. 在什么时候更新本地的缓存资源的相关信息?建议是在下载并解压资源文件到指定缓存目录后,再更新补丁的相关缓存信息,因为这个信息,读取图片时,也是需要的.如果删除某个补丁,按照目前的设计,一种比较偷懒的方案就是,在服务器上放上一个新的空资源文件就可以了.NSString * source_patch_key = SOURCE_PATCH; NSUserDefaults standardUserDefaults setObject:patchInfo forKey: source_patch_key; 读取图片功能扩展此处主要涉及到的可能的技术点:1. 如何用基础的网络类库下载文件?依然是要封装一个简单函数,下载完成后,通过block传出文件临时的保存位置:-(void) downloadFileFrom:(NSString * ) urlStr completionHandler: (void ()(NSURL *location, NSError * error) completionHandler NSURL * url = NSURL URLWithString:urlStr; NSURLSessionConfiguration * defaultConfigObject = NSURLSessionConfiguration defaultSessionConfiguration; NSURLSession * defaultSession = NSURLSession sessionWithConfiguration: defaultConfigObject delegate:self delegateQueue: NSOperationQueue mainQueue; NSURLSessionDownloadTask * downloadTask = defaultSession downloadTaskWithURL:url completionHandler:(NSURL * location, NSURLResponse * response, NSError * error) completionHandler(location,error); ; downloadTask resume; 2. 如何判断bundle中是否含有某文件?可以使用 fileExistsAtPath,但其实使用 -pathForResource: ofType: 就够了,因为找不到资源问加你时,它返回nil,所以我们直接调用它,然后判断返回是否为 nil 即可:1NSString * imgPath = mainBundle pathForResource:imgName ofType:png; 3. 将代码如何与原有的imageNamed:逻辑合并?不需要初始复制到缓存目录 + 初始请求最新的资源补丁信息 + 代码迁移合并 + 接口优化相对完整的逻辑代码注意,按照目前的设计,就不需要初始把原来ipa中的bundle复制到缓存目录了;当缓存目录中没有相关资源时,会自动尝试从ipa中的bundle读取,bundle约定统一使用 main.bundle 来简化操作,类目,对外暴露两个方法:#import interface UIImage (imageNamed_bundle_)/* load img smart .*/+ (UIImage *)yf_imageNamed:(NSString *)imgName; /* smart update for patch */+ (void)yf_updatePatchFrom:(NSString *) pathInfoUrlStr;end App启动时,或在其他合适的地方,要注意检查有无更新:- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions / Override point for customization after application launch. /* fetch pathc info every time */ NSString * patchUrlStr = /ios122/ios_assets_hot_update/master/res/patch_04.json; UIImage yf_updatePatchFrom: patchUrlStr; return YES; 内部实现,优化了许多,但也算不上复杂:#import UIImage+imageNamed_bundle_.h#import implementation UIImage (imageNamed_bundle_) + (NSString *)yf_sourcePatchKey return SOURCE_PATCH; + (void)yf_updatePatchFrom:(NSString *) pathInfoUrlStr self yf_fetchPatchInfo: pathInfoUrlStr completionHandler:(NSDictionary *patchInfo, NSError *error) if (error) NSLog(fetchPatchInfo error: %, error); return; NSString * urlStr = patchInfo objectForKey: url; NSString * md5 = patchInfo objectForKey:md5; NSString * oriMd5 = NSUserDefaults standardUserDefaults objectForKey: self yf_sourcePatchKey objectForKey:md5; if (oriMd5 isEqualToString:md5) / no update return; self yf_downloadFileFrom:urlStr completionHandler:(NSURL *location, NSError *error) if (error) NSLog(download file url:% error: %, urlStr, error); return; NSString * patchCachePath = self yf_cachePathFor: md5; SSZipArchive unzipFileAtPath:location.path toDestination: patchCachePath overwrite:YES password:nil error:&error; if (error) NSLog(unzip and move file error, with urlStr:% error:%, urlStr, error); return; /* update patch info. */ NSString * source_patch_key = self yf_sourcePatchKey; NSUserDefaults standardUserDefaults setObject:patchInfo forKey: source_patch_key; ; ; + (NSString *)yf_relativeCachePathFor:(NSString *)md5 return patch stringByAppendingPathComponent:md5; + (UIImage *)yf_imageNamed:(NSString *)imgName NSString * bundleName = main; /* cache dir */ NSString * md5 = NSUserDefaults standardUserDefaults objectForKey: self yf_sourcePatchKey objectForKey:md5; NSString * relativeCachePath = self yf_relativeCachePathFor: md5; return self yf_imageNamed: imgName bundle:bundleName cacheDir: relativeCachePath; + (UIImage *)yf_imageNamed:(NSString *)imgName bundle:(NSString *)bundleName cacheDir:(NSString *)cacheDir NSArray * LibraryPaths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES); bundleName = NSString stringWithFormat:%.bundle,bundleName; NSString * ipaBundleDir = NSBundle mainBundle.resourcePath; NSString * cacheBundleDir = ipaBundleDir; if (cacheDir) cacheBundleDir = LibraryPaths objectAtIndex:0 stringByAppendingFormat:/Caches stringByAppendingPathComponent:cacheDir; imgName = NSString stringWithFormat:%3x,imgName; NSString * bundlePath = cacheBundleDir stringByAppendingPathComponent: bundleName; NSBundle * mainBundle = NSBundle bundleWithPath:bundlePath; NSString * imgPath = mainBundle pathForResource:imgName ofType:png; /* try load from ipa! */ if ( ! imgPath & ! ipaBundleDir isEqualToString: cacheBundleDir) bundlePath = ipaBundleDir stringByAppendingPathComponent: bundleName; mainBundle = NSBundle WithPath:bundlePath; imgPath = mainBundle pathForResource:imgName ofType:png; UIImage * image; static NSString * model; if (!model) model = UIDevice currentDevicemodel; if (model isEqualToString:iPad) NSData * imageData = NSData dataWithContentsOfFile: imgPath; image = UIImage imageWithData:imageData scale:2.0; else image = UIImage imageWithContentsOfFile: imgPath; return image; + (void)yf_fetchPatchInfo:(NSString *) urlStr completionHandler:(void ()(NSDictionary * patchInfo, NSError * error)completionHandler NSURLSessionConfiguration *defaultConfigObject = NSURLSessionConfiguration defaultSessionConfiguration; NSURLSession *defaultSession = NSURLSession sessionWithConfiguration: defaultConfigObject delegate: nil delegateQueue: NSOperationQueue mainQueue; NSURL * url = NSURL URLWithString:urlStr; NSURLSessionDataTask * dataTask = defaultSession dataTaskWithURL:url completionHandler:(NSData *data, NSURLResponse *response, NSError *error) NSDictionary * patchInfo = NSJSONSerialization JSONObjectWithData:data options:0 error:&error; completionHandler(patchInfo, error); ; dataTask resume; + (void) yf_downloadFileFrom:(NSStr
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年电力系统数字化转型项目可行性研究报告及总结分析
- 2025年儿童数字教育产品开发项目可行性研究报告及总结分析
- 2025年人工智能辅助机器人在家居领域的应用可行性研究报告及总结分析
- 京考税务面试题目及答案
- 干部教育培训的重点方向和实施策略
- 教师副职笔试题及答案
- 2026年山西省大同市单招职业适应性测试必刷测试卷带答案解析
- 2026年河北工业职业技术大学单招职业适应性测试题库附答案解析
- 2026年安阳职业技术学院单招职业适应性测试必刷测试卷带答案解析
- 2026年庆阳职业技术学院单招职业技能测试必刷测试卷附答案解析
- 企业安防监控系统采购合同范本
- 消防救援专业职业生涯规划
- 甲方聘请监理协议书
- 山东省公务员2025年考试行测真题预测专项训练试卷(含答案)
- 外科急腹症手术护理
- 罗斯福新政课件知识导图
- 2025及未来5年可控硅调节器项目投资价值分析报告
- ASD挑食与进食行为矫正方案
- 电力公司法制讲座课件
- 2025年中式烹调师(技师)理论考试笔试试题附答案
- 《红岩》名著导读好书
评论
0/150
提交评论