分享

MKN与AFN对比学习

 叹落花 2015-07-31

总结在前:
    1. MKN封装了GET和POST参数,直接用Dictionary对象传入即可;而AFN需要自己手动组装NSURLRequest对象
    2. MKN有超时设置;AFN在GET条件下设置的NSURLRequest能起作用,但在POST条件下不启用(原因是apple内部机制,固定为240s)
    3. MKN自带有线程池(wifi时最大数为6;wwan时最大数为2);AFN需要自定义线程池
    4. 两者使用的方式基本一直,甚至连代码的行数都能一一对应。
    5. MKN更新进度时的BLOCK参数直接就是进度的百分比;而AFN是三个参数:当前交互数据量、已经交互累计数据量、总的需要交互的数据量,然后自己计算progress
    6. 都是采用异步操作方式,没有同步!(需要同步操作的话,只有采用最原始的NSURLConnection和NSString的静态下载方法)
    7. 都有JSON和XML解析专用方法;image异步下载专用方法
    8. AFN的AFHTTPClient相当于MKN的MKNetworkEngine,封装了一些简单方法,但没有MKN集成度高

AFN源码:https://github.com/AFNetworking/AFNetworking
AFNQA:https://github.com/AFNetworking/AFNetworking/wiki/AFNetworking-FAQ

一、MKN vs AFN 下载数据 

复制代码
    //-----------------------------
    //---------MKN下载数据----------
    //-----------------------------
    MKNetworkEngine *MKN = [[MKNetworkEngine alloc]  initWithHostName:nil customHeaderFields:nil];//自带了缓存策略;线程池(wifi最大6,wwan最大2);freeze
    MKNetworkOperation *netOp= [MKN operationWithURLString:downLoadUrl params:nil httpMethod:@"GET"];//继承自NSOperation
    [netOp addDownloadStream:[NSOutputStream outputStreamToFileAtPath:@"test.pdf" append:NO]];//定义输出流
    //----------显示下载进度-------------------------------------------------------------------------
    MBProgressHUD *HUD = [[MBProgressHUD alloc] initWithView:self.view];
    [self.view addSubview:HUD];
    HUD.tag=1000;
    HUD.mode = MBProgressHUDModeDeterminate;
    HUD.labelText = @"正在下载...";
    HUD.square = YES;
    [HUD show:YES];
    [netOp onDownloadProgressChanged:^(double progress) {HUD.progress = progress;}];//显示进度条
    //--------------------------------------------------------------------------------------------
    [netOp onCompletion:^(MKNetworkOperation* completedRequest) {[HUD removeFromSuperview];}//完成
                onError:^(NSError* error) {[HUD removeFromSuperview];}];
    [MKN enqueueOperation:netOp];//启动线程也可以用[netOp start]


    //-----------------------------
    //---------AFN下载数据----------
    //-----------------------------
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:pdfurl]];//封装下载对象(get,post数据等)
    //--------封装POST数据,键值对(GET访问就不需要)
    NSData *postData = [[postString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]dataUsingEncoding:NSUTF8StringEncoding];//将键值对(key=value&key=value)封装为NSData
    [request setHTTPMethod:@"POST"];
    [request setValue:[NSString stringWithFormat:@"%d",[postData length]] forHTTPHeaderField:@"Content-Length"];//设置NSData长度
    [request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
    [request setHTTPBody:postData];//设置body
    //-----------------------------
    AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];////继承自NSOperation
    operation.outputStream = [NSOutputStream outputStreamToFileAtPath:BillFile(pdfNameExt) append:NO];//定义输出流
    //----------显示下载进度-------------------------------------------------------------------------
    MBProgressHUD *HUD = [[MBProgressHUD alloc] initWithView:self.view];
    [self.view addSubview:HUD];
    HUD.tag=1000;
    HUD.mode = MBProgressHUDModeDeterminate;
    HUD.labelText = @"正在下载...";
    HUD.square = YES;
    [HUD show:YES];
    [operation setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) {//显示进度条
        HUD.progress = (totalBytesRead*1.0) / totalBytesExpectedToRead;}];
    //--------------------------------------------------------------------------------------------
    [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {[HUD removeFromSuperview];} //完成
                                     failure:^(AFHTTPRequestOperation *operation, NSError *error) {[HUD removeFromSuperview];}];
    [operation start];//这里可以自定义一个线程池NSOperationQueue,然后设置最大线程数,调用addOperation
复制代码


二、MKN vs AFN 上传数据  

复制代码
    //-----------------------------
    //---------MKN上传数据----------
    //-----------------------------
    MKNetworkEngine *MKN = [[MKNetworkEngine alloc] initWithHostName:nil];
    MKNetworkOperation *netOp = [MKN operationWithURLString:uploadUrl params:[NSDictionary dictionaryWithObjectsAndKeys:AppSession.deviceId,@"deviceId",nil] httpMethod:@"POST"];
    [netOp addFile:BillFile(newBillName) forKey:@"image"];//添加文件 addFilePath:forFileName
    [netOp setFreezable:YES];//设置保持
    //----------显示上传进度-------------------------------------------------------------------------
    MBProgressHUD *HUD = [[MBProgressHUD alloc] initWithView:self.view];
    [self.view addSubview:HUD];
    HUD.mode = MBProgressHUDModeDeterminate;
    HUD.labelText = @"正在上传...";
    HUD.square = YES;
    [HUD show:YES];
    [netOp onUploadProgressChanged:^(double progress) {HUD.progress = progress;}];//显示进度条
    //--------------------------------------------------------------------------------------------
    [netOp onCompletion:^(MKNetworkOperation* completedRequest) {[HUD removeFromSuperview];}//完成
                onError:^(NSError* error) {[HUD removeFromSuperview];}];
    [MKN enqueueOperation:netOp];//启动线程也可以用[netOp start]


    //-----------------------------
    //---------AFN上传数据(未测试)----------
    //-----------------------------
    //NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:pdfurl]];//
    NSData *imageData = UIImagePNGRepresentation(image);//将图片文件转换为NSData(官方只给了图片上传方法,其它任何类型的文件上传有待测试)
    AFHTTPClient *client = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:@"192.168.1.106"]];
    NSMutableURLRequest *request = [client multipartFormRequestWithMethod:@"POST" path:@"/upload" parameters:nil constructingBodyWithBlock: ^(id <AFMultipartFormData>formData) {
                                   [formData appendPartWithFileData:imageData name:@"avatar" fileName:@"avatar.jpg" mimeType:@"image/jpeg"];}];
    AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];////继承自NSOperation    
    //----------显示下载进度-------------------------------------------------------------------------
    MBProgressHUD *HUD = [[MBProgressHUD alloc] initWithView:self.view];
    [self.view addSubview:HUD];
    HUD.tag=1000;
    HUD.mode = MBProgressHUDModeDeterminate;
    HUD.labelText = @"正在下载...";
    HUD.square = YES;
    [HUD show:YES];
    [operation setUploadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) {//显示进度条
        HUD.progress = (totalBytesRead*1.0) / totalBytesExpectedToRead;}];
    //--------------------------------------------------------------------------------------------
    [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {[HUD removeFromSuperview];} //完成
                                     failure:^(AFHTTPRequestOperation *operation, NSError *error) {[HUD removeFromSuperview];}];
    [operation start];//这里可以自定义一个线程池NSOperationQueue,然后设置最大线程数,调用addOperation
复制代码


三、多线程批量下载文件,没下载完成的后缀为.temp;采用线程池 最大同时运行3个分线程;当下载完成时去掉后缀.temp,并删除临时文件

复制代码
//函数作用: 多线程批量下载文件,没下载完成的后缀为.temp
//         采用线程池 最大同时运行3个分线程
//         当下载完成时去掉后缀.temp,并删除临时文件
//参数:array: 待下载的文件列表,每个文件的描述是NSDictionary,至少包括三个key——filename、filesize、filelink
// path: 待下载文件保存的文件夹路径
//说明:该函数完成后,会发送线程同步消息;FileManager可以在这里(iOS开发知识体系——File Manager)找到源码
- (void)doDownloading:(NSMutableArray *)array toFolder:(NSString *)path{ //---------------------------------过滤不需要下载的文件---------------------------------------------------- NSMutableArray *arrayLocal = [FileManager allFilesAttributeInFolderPath:path];//获取本地目录下所有文件的filename和filesize信息 for (NSDictionary *temp in arrayLocal) {//外循环是本地文件数组 NSString *filename = [temp objectForKey:@"filename"]; NSString *filesize = [temp objectForKey:@"filesize"]; BOOL fileExists = NO; for (NSDictionary *temp1 in array) {//内循环是待下载的文件数组 NSString *filename1 = [temp1 objectForKey:@"filename"]; NSString *filesize1 = [temp1 objectForKey:@"filesize"]; if ([filename1 isEqualToString:filename]) { fileExists = YES; if ([filesize isEqualToString:filesize1]) { //只要文件名和大小一致就表示没必要下载 [array removeObject:temp1]; } break; } } //删除过时的文件 if (!fileExists)[FileManager fileDelete:[path stringByAppendingPathComponent:filename]]; } arrayLocal = nil;//释放内存 //----------------------------------------------------------------------------------------------------- //---------------------------------启动下载线程----------------------------------------------------------- if (array.count>0) { NSOperationQueue *queue = [[NSOperationQueue alloc] init]; //线程池 [queue setMaxConcurrentOperationCount:3]; //最大同时运行的线程数 __block int arrayIndex = 0; //用于判断线程池里的线程是否都结束 for (NSDictionary *dictTemp in array) {//遍历目标下载数组并启动下载 NSString *filelink = [dictTemp objectForKey:@"filelink"]; //文件的下载地址 NSString *filename = [dictTemp objectForKey:@"filename"]; //文件名 NSString *filePath = [NSString stringWithFormat:@"%@/%@",path,filename]; //下载后保存文件的绝对路径 NSString *filePathTemp = [NSString stringWithFormat:@"%@/%@.temp",path,filename]; //临时下载的文件路径 AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:filelink]]]; operation.outputStream = [NSOutputStream outputStreamToFileAtPath:filePathTemp append:NO]; [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {if(![FileManager fileCopy:filePathTemp TargetName:filePath]){[FileManager fileDelete:filePath];} [FileManager fileDelete:filePathTemp]; arrayIndex++; if (arrayIndex==array.count) {[condition signal];}//发送线程同步消息 } failure:^(AFHTTPRequestOperation *operation, NSError *error) { [FileManager fileDelete:filePathTemp]; arrayIndex++; if (arrayIndex==array.count) {[condition signal];}//发送线程同步消息 }]; [queue addOperation:operation]; } }else{ [condition signal];//发送线程同步消息 } //----------------------------------------------------------------------------------------------------- }
复制代码

 

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多