以下是iOS app熱更新的幾種方案,
由于蘋果在2017年3月左右更新了開發(fā)者協(xié)議, 禁止需要線上審核的應(yīng)用進(jìn)行熱更新, 所以請大家慎用
(企業(yè)版不需要提交審核當(dāng)然是可以使用的)
目前流行的熱更新解決方案可以參看這篇文章:http://blog.csdn.net/chengkaizone/article/details/64122587
這里主要介紹使用framework進(jìn)行熱更新的方法
具體步驟:
- 封裝framework ,不在介紹 可參見我的另一篇文章framework封裝
- 把封裝好的框架上傳到服務(wù)端,我這里是上傳到了我的Github
- 項(xiàng)目中下載框架
- 讀取框架 展示
框架展示思路

未命名文件.png
1.判斷本地是否存在framework
#pragma mark - 下載以及比較文件
-(void)compareAndLoadFile{
NSArray *arrFramework = [self getFilenamelistOfType:@"framework" fromDirPath:_destinationPath];
NSString *bundlePath = [NSString stringWithFormat:@"%@/%@",_destinationPath,[arrFramework lastObject]];
NSLog(@"path===%@",bundlePath);
if (![[NSFileManager defaultManager] fileExistsAtPath:bundlePath]) {
NSLog(@"文件不存在");
NSString *requestURL = Download_Url;
if(requestURL==nil || requestURL.length==0){
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"提示" message:@"沒有下載地址,不能開啟" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *sureBtn = [UIAlertAction actionWithTitle:@"確定" style:UIAlertActionStyleDefault handler:nil];
[alertController addAction:sureBtn];
return;
}else{
NSLog(@"去下載");
[self downloadFile];
}
}else{
NSLog(@"文件存在!");
// 重新下載文件 命名不同
[self reDownloadFile];
}
}
下載方法
-(void)downloadFile{
//下載保存的路徑
NSString *savedPath = [NSHomeDirectory() stringByAppendingString:[NSString stringWithFormat:@"/Documents/HotPatch-master.zip"]];
AFHTTPRequestSerializer *serializer = [AFHTTPRequestSerializer serializer];
NSMutableURLRequest *request = [serializer requestWithMethod:@"GET" URLString:Download_Url parameters:nil error:nil];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc]initWithRequest:request];
[operation setOutputStream:[NSOutputStream outputStreamToFileAtPath:savedPath append:NO]];
[operation setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) {
float progress = (float)totalBytesRead / totalBytesExpectedToRead;
_progressView.progress =progress;
_progressLabel.text = [NSString stringWithFormat:@"%.2f%%",progress*100];
NSLog(@"progress==%.2f",progress);
}];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation * _Nonnull operation, id _Nonnull responseObject) {
NSLog(@"下載成功");
NSString *destinationPath = [NSHomeDirectory() stringByAppendingString:[NSString stringWithFormat:@"/Documents"]];
//對下載下來的ZIP包進(jìn)行解壓
BOOL isScu = [SSZipArchive unzipFileAtPath:savedPath toDestination:destinationPath];
if(isScu){
NSLog(@"解壓成功");
NSFileManager *fileMgr = [NSFileManager defaultManager];
BOOL bRet = [fileMgr fileExistsAtPath:savedPath];
if (bRet) {
[fileMgr removeItemAtPath:savedPath error:nil];//解壓成功后刪除壓縮包
}
[self reloadFramework];
}else{
NSLog(@"解壓失敗 --- 開啟失敗");
}
} failure:^(AFHTTPRequestOperation * _Nonnull operation, NSError * _Nonnull error) {
NSLog(@"error===%@",error);
NSLog(@"下載失敗 --- 開啟失敗");
}];
[operation start];
}
比較兩個文件是否相同的方法:
-(void)compareFile{
NSArray *arrFramework = [self getFilenamelistOfType:@"framework" fromDirPath:_destinationPath];
NSString *bundlePath = [NSString stringWithFormat:@"%@/%@",_destinationPath,[arrFramework lastObject]];
_filePathOne = bundlePath;
NSLog(@"_filePathOne===%@",_filePathOne);
//獲取framework的路徑名
NSArray *arrFrameworkX = [self getFilenamelistOfType:@"framework" fromDirPath:_newPath];
NSString *bundlePathX = [NSString stringWithFormat:@"%@/%@",_newPath,[arrFrameworkX lastObject]];
_filepathTwo = bundlePathX;
NSLog(@"_filepathTwo==%@",_filepathTwo);
if ([[NSFileManager defaultManager] contentsEqualAtPath:_filePathOne andPath:_filepathTwo]) {
NSLog(@"文件相同");
[[NSFileManager defaultManager] removeItemAtPath:_destinationPathX error:nil];//刪除下載的文件
[self reloadFramework];
}else{
NSLog(@"文件不同");
[[NSFileManager defaultManager] removeItemAtPath:_destinationPath error:nil];//刪除舊的下載的文件
// 移動文件到Documents文件下
NSError *error = nil;
if ([[NSFileManager defaultManager] moveItemAtPath:_newPath toPath:_destinationPath error:&error] == YES){
[[NSFileManager defaultManager] removeItemAtPath:_destinationPathX error:nil];//刪除舊的文件
NSLog(@"重命名成功!");
[self reloadFramework];
}else{
NSLog(@"Unable to move file: %@", [error localizedDescription]);
}
}
}
加載framework的方法
#pragma mark - 加載framework
-(void)reloadFramework{
NSArray *arrFramework = [self getFilenamelistOfType:@"framework" fromDirPath:_destinationPath];
NSString *bundlePath = [NSString stringWithFormat:@"%@/%@",_destinationPath,[arrFramework lastObject]];
NSLog(@"bundlePath==%@",bundlePath);
_filePathOne = bundlePath;
NSBundle *bundle = [NSBundle bundleWithPath:bundlePath];
if (!bundle || ![bundle load]) {
NSLog(@"bundle加載出錯");
}
// 下載的framework的封裝的文件名
NSString *className = @"HotPatchViewController";
NSString *classtype = @"UIViewController";
Class loadClass = [bundle classNamed:className];
if (!loadClass) {
NSLog(@"獲取失敗");
}
if([classtype isEqualToString:@"UIViewController"]){
NSLog(@"成功了。。。");
UIViewController *uvc = (UIViewController*)[loadClass new];
[self.navigationController pushViewController:uvc animated:YES];
}
}
最后項(xiàng)目源碼:Cxm的Github