MKNetworkKit框架入门及简单用法

1.什么是MKNetWorkKit?

MKNetWorkKit是一个用OC语言编写的网络框架,支持block块和ARC;并且MKNetWorkKit的用法简单.

MKNetWorkKit是集成了ASIHTTPRequest和 AFNetworking

两个框架于一体,在集成两者的优点之外,自己还增加了很多新的特性.

2. MKNetWorkKit的优点

   1、整个框架只有一些类别方法和两个类(MKNetworkEngine和MKNetworkOperation)所以它使用起来很简便

   2、自主操作多个网络请求;

   3、更加准确的显示网络活动指标;

   4、自动设置网络速度,实现自动的2G、3G、wifi切换;

   5、自动缓冲技术的完美应用,实现网络操作记忆功能,当你掉线了又上线后,会继续执行未完成的网络请求;

   6、可以实现网络请求的暂停功能;

   7、准确无误的成功执行一次网络请求,摒弃后台的多次请求浪费;

   8、支持图片缓冲;

   9、支持ARC机制;

   10、在整个app中可以只用一个队列(queue),队列的大小可以自动调整。

3.如何配置MKNetworkKit?

   1、从https://github.com/MugunthKumar/MKNetworkKit下载MKNetworkKit;

   2、将下载包中的 MKNetWorkKit 文件夹拖到你新建的工程中;

   3、在项目设置中添加:SystemConfiguration.framework,CFNetwork.framework,Security.framework和ImageIO.framework

4.怎么进行网络请求?

MKNetworkKit中主要有两个类:MKNetworkOperation和MKNetworkEngine。MKNetworkOperation是NSOperation的子类并且封装了请求相应类,我们需要为每一个网络请求创建一个MKNetworkOperation。MKNetworkEngine负责管理网络队列,对于简单的请求,我们应该直接使用MKNetworkEngine的方法,对于复杂的需求,我们可以子类化MKNetworkEngine。

5.MKNetworkKit中的一些简便用法

MKNetworkKit的一些简便用法:

1.           responseData

2.           responseString

3.           responseJSON (Only on iOS 5以上)

4.           responseImage

5.           responseXML

6.           error

6.一个利用MKNetworkKit网络请求(GET请求)的天气预报DEMO

效果图:

效果图

 //请求路径.是在主机名之后显示的,可以与主机名进行拼接,拼接成一个完整的url
    NSString *path = [[NSString alloc] initWithFormat:@"//data/sk/%@.html",cityID];
    
    //创建一个MKNetworkEngine对象,注意initWithHostName后面是主机名
    //.....MKNetworkEngine负责管理网络队列NSOperationQueue
    __block MKNetworkEngine *engine = [[MKNetworkEngine alloc] initWithHostName:@"www.weather.com.cn" customHeaderFields:nil];

    //创建一个MKNetworkOperation对象
    //MKNetworkOperation是NSOperation的子类并且封装了请求相应类
    //在进行网络请求是需要为每一个网络请求创建一个MKNetworkOperation
    MKNetworkOperation *op = [engine operationWithPath:path params:nil httpMethod:@"GET"];
    
    //指定请求的代码块,网络请求成功时回调代码块addCompletionHandler,失败时回调errorHandler的block代码块
    [op addCompletionHandler:^(MKNetworkOperation *completedOperation) {
        //通过MKNetworkOperation中的responseData方法直接获取url中的数据.并且存放在NSData中
//        NSData *data = [completedOperation responseData];
//        //对拿到的数据进行json解析,系统给出的json解析
//        result = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
//        result = [result objectForKey:@"weatherinfo"];
        //利用MKNetworkKit给的json解析进行解析数据
        result =  [[completedOperation responseJSON] objectForKey:@"weatherinfo"];
        self.cityLabel.text = [result objectForKey:@"city"];
        self.tempLabel.text = [result objectForKey:@"temp"];
        self.wdLabel.text = [result objectForKey:@"WD"];
        self.wlLabel.text = [result objectForKey:@"WS"];
        self.sdLabel.text = [result objectForKey:@"SD"];
        self.timeLabel.text = [result objectForKey:@"time"];
        
        } errorHandler:^(MKNetworkOperation *completedOperation, NSError *error) {
        
        NSLog(@"%@",[error localizedDescription]);
        
        engine = nil;
        
    }];
    //发起网络请求
    [engine enqueueOperation:op];

post请求

效果图:


 // 转成专门用于URL的格式www.weather.com.cn/data/sk/101010300.html   101010300是城市ID
    NSString *host = @"www.weather.com.cn";
    // 域名(host)后面跟着的路径,
    NSString *path = [NSString stringWithFormat:@"//data/sk/%@.html",cityID];
    
    // 目标URL:www.weather.com.cn/data/sk/101010300.html
    
    // 需要发送的参数
    NSMutableDictionary *params = [[NSMutableDictionary alloc] init];
    [params setValue:cityID forKey:@"cityID"];
    
    // path 值可以放到 engine 的初始化中,也可以放到 operation 的初始化中,效果一样
    MKNetworkEngine *engine = [[MKNetworkEngine alloc] initWithHostName:host apiPath:path customHeaderFields:nil];
    MKNetworkOperation *operation = [engine operationWithPath:nil params:params httpMethod:@"POST"];
    
    // 添加网络请求完成处理逻辑
    [operation addCompletionHandler:^(MKNetworkOperation *completedOperation) {
        NSLog(@"POST请求完成");
        
        self.wetherText.text = [completedOperation responseString];
    } errorHandler:^(MKNetworkOperation *completedOperation, NSError *error) {
        NSLog(@"POST请求出错");
        
        self.wetherText.text = [NSString stringWithFormat:@"请求出错: %@", error];
    }];
    
    // 发送网络请求
    [engine enqueueOperation:operation];

下载文件

效果如下图:

核心代码:
- (IBAction)LoadButton:(UIButton *)sender {
//获取缓存路径.
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
    NSString *cachepath = [paths objectAtIndex:0];//得到缓存的路径
    //进行拼接得到文件下载后缓存的路径
    NSString *downloadPath = [cachepath stringByAppendingString:@"mmm.zip"];
    [_engine addDownLoadTaskInQueue:url tofilePath:downloadPath breakpointResum:YES
     rewriteFile:(BOOL)NO];
}

- (IBAction)pauseButton:(UIButton *)sender {
    [_engine cancelDownloadFileTaskInQueue:url];
}

- (IBAction)deleteButton:(UIButton *)sender {
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
    NSString *cachepath = [paths objectAtIndex:0];//得到缓存的路径
    //进行拼接得到文件下载后缓存的路径
    NSString *downloadPath = [cachepath stringByAppendingString:@"mmm.zip"];
    NSFileManager *fileManage = [NSFileManager defaultManager];
    if ([fileManage fileExistsAtPath:downloadPath]) {
        [fileManage removeItemAtPath:downloadPath error:nil];
    }
}

子类化的MKNetworkEngine:
.h文件
#import "MKNetworkEngine.h"
@class DownLoadEngine;
@class DownLoadOperation;

@protocol DownLoadEngineDelegate
//创建一个改变progress的方法
- (void)changeprogress:(double)changeProgress
         withOperation:(DownLoadOperation *)operation
            withEngine:(DownLoadEngine *)engine;
//下载完成时
- (void)downloadEngineDidFinsh:(DownLoadEngine*)engine
                 withOperation:(DownLoadOperation *)operation;
//下载任务已经存在
- (void)downloadEngineDownloadExist:(DownLoadEngine *)engine
                             withURL:(NSString *)paramURL;
//下载文件已经存在
- (void)downloadEngineDownloadDone:(DownLoadEngine *)engine
                            withURL:(NSString *)paramURL;
//暂停下载
- (void)downloadEnginePauseTask:(DownLoadEngine *)engine
                         withURL:(NSString *)paramURL;



@end
@interface DownLoadEngine : MKNetworkEngine
@property(nonatomic,retain)NSMutableArray *allDownloads;//用来存放任务的数组
@property(nonatomic,assign)id<DownLoadEngineDelegate> delegate;
//DownLoadEngine的单例方法
+ (id)sharDownLoadEngine;
//暂停所有任务的方法
- (void)cancelAllOperations;
//将所有的下载任务放到一个队列中
- (void)addDownLoadTaskInQueue:(NSString *)urlString//要下载的文件的url路径
                    tofilePath:(NSString *)paramPathparamFilePath是下载的文件下载完存放的路径.
               breakpointResum:(BOOL)resum
                   rewriteFile:(BOOL)paramRewrite;//是否支持断点续传
- (void)cancelDownloadFileTaskInQueue:(NSString *)paramURL;//暂停或取消指定的任务的方法


.m文件
- (void)addDownLoadTaskInQueue:(NSString *)urlString
                    tofilePath:(NSString *)paramPath
               breakpointResum:(BOOL)resum
                   rewriteFile:(BOOL)paramRewrite
{
    //获得临时文件的路径
    // 获取主目录下的tmp目录路径,用来存放下载的文件的临时文件(缓存路径)
    NSString *temPath = NSTemporaryDirectory();
    NSCharacterSet *set = [NSCharacterSet characterSetWithCharactersInString:@"/"];
    NSRange lastRange = [paramPath rangeOfCharacterFromSet:set options:NSBackwardsSearch];
    //拼接得到下载文件的缓存目录
    NSString *temfilePath = [NSString stringWithFormat:@"%@%@.temp",temPath,[paramPath substringFromIndex:lastRange.location+1]];
    
    //创建operation
    DownLoadOperation *operation = [DownLoadOperation operationUrlWithString:urlString
                                                                      params:nil httpMethod:@"GET" tempFilePath:temfilePath downloadFilePath:paramPath
                                                                 rewriteFile:paramRewrite];
    //判断文件是否下载

    //创建一个BOOL值
    BOOL exitsDownLoad = NO;
    for (DownLoadOperation *op in self.allDownloads) {
        if ([op.url isEqualToString:operation.url]) {
            exitsDownLoad = YES;
            NSLog(@"正在下载");
        }
    }
    if (exitsDownLoad) {
        [[self delegate] downloadEngineDownloadExist:self withURL:urlString];
    }else if (operation == nil ){
        [[self delegate] downloadEngineDownloadDone:self withURL:urlString];
    }else
    {
        [self enqueueOperation:operation];//发起网络请求
        [self.allDownloads addObject:operation];
        //onDownloadProgressChanged:^(double progress)此方法为MKNetworkKit中的方法
        //下载进度改变时回调方法downloadManager: withOperation: changeProgress:
        [operation onDownloadProgressChanged:^(double progress) {
            [[self delegate] changeprogress:progress withOperation:operation withEngine:self];
        }];
        
        //当任务完成都回调此方法.将下载在缓存中的文件移到指定的目录中存放
        [operation onCompletion:^(MKNetworkOperation *completedOperation) {
            NSFileManager *fileManager =[[NSFileManager alloc] init];
            NSError *error = nil;
            // 下载完成以后 先删除之前的文件 然后mv新的文件
            //fileExistsAtPath判断paramFilePath是否存在,即是否下载完成
            if ([fileManager fileExistsAtPath:paramPath]) {
                [fileManager removeItemAtPath:paramPath error:&error];
                if (error) {
                    exit(-1);
                }
            }
            //判断paramFilePath是否存在,若存在则将其移到tempFilePath文件中

            [fileManager moveItemAtPath:temfilePath toPath:paramPath error:&error];
            if (error) {
                exit(-1);
            }

            //将operation从数组中移除
            [[self delegate] downloadEngineDidFinsh:self withOperation:(DownLoadOperation *)completedOperation];
            [self.allDownloads removeObject:operation];
            
            
        } onError:^(NSError *error) {
            NSLog(@"出错了");
        }];
    }
}
//暂停下载
- (void)cancelDownloadFileTaskInQueue:(NSString *)urlString
{
    DownLoadOperation *deleteOperation = nil;
    for (DownLoadOperation *op in self.allDownloads) {
        if ([op.url isEqualToString:urlString]) {
            deleteOperation = op;
        }
    }
    [[self delegate] downloadEnginePauseTask:self withURL:urlString];
    [deleteOperation cancel];
    [self.allDownloads removeObject:deleteOperation];
}
//暂停所有的下载'

- (void)cancelAllOperations
{
    for (DownLoadOperation *op in self.allDownloads) {
        [op cancel];
    }
    [self.allDownloads removeAllObjects];
}

子类化的MKNetworkOperation:
.h文件
#import "MKNetworkOperation.h"

@interface DownLoadOperation : MKNetworkOperation
{
    
    NSString *tempFilePath;
    NSString *downloadFilePath;
}

//tempFilePath:(NSString *)tempFilePath下载文件时存放缓存路径
//downloadFilePath:(NSString *)downloadFilePath文件完后存放的路径

+(DownLoadOperation *)operationUrlWithString:(NSString *)urlString
                                      params:(NSMutableDictionary *)params
                                  httpMethod:(NSString *)method
                                tempFilePath:(NSString *)tempFilePath
                            downloadFilePath:(NSString *)downloadFilePath
                                 rewriteFile:(BOOL)rewrite;

.m文件
+(DownLoadOperation *)operationUrlWithString:(NSString *)urlString
                                      params:(NSMutableDictionary *)params
                                  httpMethod:(NSString *)method
                                tempFilePath:(NSString *)tempFilePath
                            downloadFilePath:(NSString *)downloadFilePath
                                 rewriteFile:(BOOL)rewrite
{
    //获得缓存的路径
    // 创建文件管理器
    NSFileManager *fileMgr = [NSFileManager defaultManager];
    //初始化消息头
    NSMutableDictionary *headersDic = [[NSMutableDictionary alloc] init];
    //下载文件时或重新下载时
    //首先判断缓存中是否有下载中的文件,如果有删除,没有则到文件下载完成后存放的路径中查看是否有下载好的文件,若有将其删除
    //断点续传的关键在于rewriteFile:(BOOL)rewrite这个BOOL值..
    if (rewrite &&[fileMgr fileExistsAtPath:tempFilePath]) {
//        NSError *error = nil;
//        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"" message:@"文件已经存在是否继续下载" delegate:self cancelButtonTitle:@"确定" otherButtonTitles:@"取消", nil];
//        [alert show];
        [fileMgr removeItemAtPath:tempFilePath error:nil];
    }else if (rewrite &&[fileMgr fileExistsAtPath:downloadFilePath]){
        NSError *error = nil;
        [fileMgr removeItemAtPath:downloadFilePath error:&error];
    }
    
    //判断文件是否下载
    //若没有下载则下载文件.并构建下载进度.下载中则返回空
    if ([fileMgr fileExistsAtPath:downloadFilePath]) {
        return nil;
    }else {
//[[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString *)kCFBundleNameKey]是获得该工程下载文件的
//[[[NSBundle mainBundle] infoDictionary]objectForKey:(NSString *)kCFBundleVersionKey]]获得版本号
        NSString *userAgentString = [NSString stringWithFormat:@"%@/%@",
                                     [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString *)
                                         kCFBundleNameKey],
                                     [[[NSBundle mainBundle] infoDictionary]objectForKey:(NSString *)kCFBundleVersionKey]];
        [headersDic setObject:userAgentString forKey:@"momo"];
        
        //判断之前是否下载 若下载则重新构造header(消息头)
        if ([fileMgr fileExistsAtPath:tempFilePath]) {
            
        NSError *error = nil;
            //通过计算大小可以算出下载到那里暂停的,继续下载时会从之前暂停的地方继续下载
        unsigned long long fileSize = [[fileMgr attributesOfItemAtPath:tempFilePath error:&error]fileSize];
        if (error) {
            NSLog(@"get %@ fileSize failed!\nError:%@", tempFilePath, error);
        }
        NSString *headerRange = [NSString stringWithFormat:@"bytes=%llu-", fileSize];

            [headersDic setObject:headerRange forKey:@"range"];
        }
        
        //初始化opertion(DownLoadOperation)
        DownLoadOperation *opertion = [[DownLoadOperation alloc]
                                       initWithURLString:urlString
                                                  params:params
                                              httpMethod:method];
        [opertion addDownloadStream:[NSOutputStream outputStreamToFileAtPath:tempFilePath append:YES]];//下载文件的流使用NSOutputStream可以将网络请求的资源回来的数据保存到本地文件
        [opertion addHeaders:headersDic];
        return opertion;
    }
    
    
}



这里大家可以借鉴几篇比较好的博文:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值