苹果开发 笔记(56)下载zip文件到沙箱更新

这两天跟同事学习IOS的更新文件的需求,他们的项目是html5打包封装的游戏,里面的文件有大量图片,音频素材,html,js文件。
现在要处理版本更新这一块。
初步需求设计预想是通过版本更新检测,请求服务器下载zip文件到沙箱进行解压处理。
示意如下:
版本号对比———-> 请求zip更新包————->写入沙箱NSDocumentDirectory—>解压覆盖旧文件 ——>清理更新包和旧的资源文件

1.准备的工作

1 .AFNetworking 2.5.4版本
2.ZipArchive
准备两个类库,AFNetworking负责下载zip文件,ZipArchive负责解压Zip文件。准备好就配置一下 其中ZipArchive 的版本调整过 配置的过程如下

Add Main.h and Main.m to your project.
Add the minizip folder to your project.
Add the libz library to your target

简单直接办法把你下载文件拖到你的工程目录去,注意黄色文件夹和蓝色文件夹不一样。
添加libz进去,引用的时候import “Main.h” (其实Main命名让人纠结,暂时凑合够用就好了)
这里写图片描述

准备工作完成后可以写一个测试用例

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController <UIAlertViewDelegate>
@end

#import "ViewController.h"
#import "AFNetworking.h"
#import "UIProgressView+AFNetworking.h"
#import "Main.h"

@interface ViewController () 
@property (nonatomic,strong) UIProgressView *progressView;
@property (nonatomic,strong) UILabel *progressLabel;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    CGRect frame = CGRectMake(10, 100, self.view.frame.size.width-20, 40);
    UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    button.frame = frame;
    [button setTitle:@"更新" forState: UIControlStateNormal];
    button.backgroundColor = [UIColor greenColor];
    [button addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:button];

    self.progressView = [[UIProgressView alloc]initWithFrame:CGRectMake(10, 200, self.view.frame.size.width-20, 2)];
    [self.view addSubview:self.progressView];

    self.progressLabel  =[[UILabel alloc] initWithFrame:CGRectMake(10, 160, 200, 20)];
    [self.view addSubview:self.progressLabel];
}

-(void) buttonClicked:(UIButton *)button
{

    UIAlertView *alert  =  [[UIAlertView alloc] initWithTitle:@"版本更新" message:@"版本发现有更新内容需要更新吗?" delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"确定", nil];

    [alert show];

}
-(void) alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{

    if(buttonIndex  == 1)
    {
        [self downloadFile:@"testZipTime.zip"
                       url:@"http://xxxxxxxxx/app/testZipTime.zip"];//换成你的地址路径
    }

}


-(void) downloadFile:(NSString *)fileName url:(NSString *) filePath
{
    NSURLSessionConfiguration *configuration  =  [NSURLSessionConfiguration defaultSessionConfiguration];

    AFURLSessionManager *manager = [[AFURLSessionManager alloc]initWithSessionConfiguration:configuration];

    NSURL *url = [NSURL URLWithString:filePath];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];

    NSURLSessionDownloadTask *downloadTask  =[manager downloadTaskWithRequest:request progress:nil destination:^NSURL *(NSURL *targetPath, NSURLResponse *response) {
        NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
        NSURL *docmentDirectoryPath = [NSURL fileURLWithPath:path];
        return [docmentDirectoryPath URLByAppendingPathComponent:fileName ];
    } completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error) {

        NSLog(@"@dowload to %@",filePath);

        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        NSString *path = [paths objectAtIndex:0];
        NSString *zipPath = [path stringByAppendingPathComponent:fileName];
        BOOL isOK = [Main unzipFileAtPath:zipPath toDestination:path];
        if(isOK)
        {
            NSLog(@"更新好了");
            [self deleteFileByName:fileName];

            dispatch_async(dispatch_get_main_queue(), ^{

                self.progressLabel.text  = @"更新成功了";
            });
        }

    }];

    [manager setDownloadTaskDidWriteDataBlock:^(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, int64_t bytesWritten, int64_t totalBytesWritten, int64_t totalBytesExpectedToWrite) {


        NSLog(@"进度数据:%f",(float)totalBytesWritten/(float)totalBytesExpectedToWrite);
        float precess  = round(((float)totalBytesWritten/(float)totalBytesExpectedToWrite ) *100);

        NSNumber *num = [[NSNumber alloc]initWithFloat:precess];

        dispatch_async(dispatch_get_main_queue(), ^{

            NSString *newStr  = [NSString stringWithFormat:@"更新进度中...%@%%",[num stringValue] ];

            self.progressLabel.text  = newStr;
        });

    }];


    [downloadTask resume];
    [self.progressView setProgressWithDownloadProgressOfTask:downloadTask animated:YES];

}


-(void) deleteFileByName:(NSString *) fileName
{

    NSFileManager *manager = [NSFileManager defaultManager];
    NSArray *docPaths  = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *path  = [docPaths objectAtIndex:0];
    path = [path stringByAppendingPathComponent:fileName];
    NSError *error = nil;
    if ([manager removeItemAtPath:path error:&error])
    {
        NSLog(@"删除文件成功了");
    }
}


- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

运行后效果图
这里写图片描述

因为经常打开沙箱文件位置查看数据包是否加装完。安装
ZLGotoSandboxPlugin 插件就能快速定位到相应的沙箱去

2.下载进度条显示

下载的进度条采用了AFNetworking 提供的便利方法
原本使用kvo 配合NSProgress 也可以显示进行的百分比,但是在测试过程发现奇怪现象数据没有触发到,于是改用另外一个方法AFURLSessionManager的setDownloadTaskDidWriteDataBlock 方法,这样百分进度就可以显示。

  setDownloadTaskDidWriteDataBlock

3.更新UI显示

采用GCD 的方法在主线程对UI进行刷新

  dispatch_async(dispatch_get_main_queue(), ^{             
      self.progressLabel.text  = @"更新成功了";
  });

4.压缩zip文件

ZipArchive 给我们提供了一个Main的方法处理压缩包,目前看来仅仅只是需要用一个简单的功能,凑合使用。这个方法需要填写两个目录路径。一个是文件路径,一个是解压的位置。这时候这个解压的反馈过程就弄好了。

 NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
 NSString *path = [paths objectAtIndex:0];
 NSString *zipPath = [path stringByAppendingPathComponent:fileName];
 BOOL isOK = [Main unzipFileAtPath:zipPath toDestination:path];

5.删除文件

解压成功后需要对原有的包进行删除,使用 NSFileManager为我们提供的方法进行删除操作。

-(void) deleteFileByName:(NSString *) fileName
{

    NSFileManager *manager = [NSFileManager defaultManager];
    NSArray *docPaths  = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *path  = [docPaths objectAtIndex:0];
    path = [path stringByAppendingPathComponent:fileName];
    NSError *error = nil;
    if ([manager removeItemAtPath:path error:&error])
    {
        NSLog(@"删除文件成功了");
    }
}

6.遇到问题

主要是对AFNetworking 框架不熟悉,使用起来也 发生被动情况。没有考虑多线程的情况,之前使用NSURLConnection的情况也出现类似的问题。
更新操作还没有考虑容量判断,防止手机容量不足更新失败情况
没有考虑断线续传的情况。
升级后批量清理旧的文件目录
下一步尝试思考这些问题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值