iOS 基于Framework的熱更新

以下是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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容