现在流行的第三方网络请求库有很多,ASIHTTPRequest、AFNetWorking等,每个人都自己的使用习惯,我推荐一个印度小伙子写的一个超轻量型框架MKNetWorkKit。 由于博客迁移至www.coderyi.com,文章请看http://www.coderyi.com/archives/422
由于博客迁移至www.coderyi.com,文章请看http://www.coderyi.com/archives/422
MKNetWorkKit是由一个印度小伙子写的,是用于网络请求的库,支持ARC,代码的网址这里给出。
作者源码地址(MugunthKumar):https://github.com/MugunthKumar/MKNetworkKit
作者关于类库介绍的地址(MugunthKumar):http://blog.mugunthkumar.com/products/ios-framework-introducing-mknetworkkit/
作者类库介绍中文翻译地址(翻译作者,csdn博主kmyhy,杨宏焱):http://blog.csdn.net/kmyhy/article/details/12276287
这里面大多数时候会引用到它里面的demo,MKNetWorkKit-iOS-Demo,本文主要是根据作者原文以及作者的demo还有自己的使用写的文章。
在整个程序中只有一个全局队列
MKNetWorkKit中主要有两个类,MKNetworkEngine和MKNetworkOperation,MKNetworkOperation就是一个操作,是NSOperation的子类,每个HTTP操作通过MKNetworkEngine入队,队列是一个NSOperationQueue,在程序是一个单例,在MKNetworkEngine的initialize里创建。
GET请求
一般自己会复写MKNetworkEngine,在这里提供一个每一个网络请求的接口,可以传入参数,请求完成和失败的block。
1
|
self.yahooEngine = [[YahooEngine alloc] initWithHostName:@
"download.finance.yahoo.com"
];
|
YahooEngine的GET请求方法的申明
1
2
3
4
|
typedef
void
(^CurrencyResponseBlock)(
double
rate);
-(MKNetworkOperation*) currencyRateFor:(NSString*) sourceCurrency
inCurrency:(NSString*) targetCurrency
completionHandler:(CurrencyResponseBlock) completion
|
GET请求方法的实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
-(MKNetworkOperation*) currencyRateFor:(NSString*) sourceCurrency
inCurrency:(NSString*) targetCurrency
completionHandler:(CurrencyResponseBlock) completionBlock
errorHandler:(MKNKErrorBlock) errorBlock {
MKNetworkOperation *op = [self operationWithPath:YAHOO_URL(sourceCurrency, targetCurrency)
params:nil
httpMethod:@
"GET"
];
[op addCompletionHandler:^(MKNetworkOperation *completedOperation)
{
// the completionBlock will be called twice.
// if you are interested only in new values, move that code within the else block
NSString *valueString = [[completedOperation responseString] componentsSeparatedByString:@
","
][1];
DLog(@
"%@"
, valueString);
if
([completedOperation isCachedResponse]) {
DLog(@
"Data from cache %@"
, [completedOperation responseString]);
}
else
{
DLog(@
"Data from server %@"
, [completedOperation responseString]);
}
completionBlock([valueString doubleValue]);
}errorHandler:^(MKNetworkOperation *errorOp, NSError* error) {
errorBlock(error);
}];
[self enqueueOperation:op];
return
op;
}
|
GET请求方法的调用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
self.currencyOperation = [ApplicationDelegate.yahooEngine currencyRateFor:@
"SGD"
inCurrency:@
"USD"
completionHandler:^(
double
rate) {
[[[UIAlertView alloc] initWithTitle:@
"Today's Singapore Dollar Rates"
message:[NSString stringWithFormat:@
"%.2f"
, rate]
delegate:nil
cancelButtonTitle:NSLocalizedString(@
"Dismiss"
, @
""
)
otherButtonTitles:nil] show];
}
errorHandler:^(NSError* error) {
DLog(@
"%@\t%@\t%@\t%@"
, [error localizedDescription], [error localizedFailureReason],
[error localizedRecoveryOptions], [error localizedRecoverySuggestion]);
}];
|
POST请求,上传一张图片
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
-(MKNetworkOperation*) uploadImageFromFile:(NSString*) file
completionHandler:(IDBlock) completionBlock
errorHandler:(MKNKErrorBlock) errorBlock {
MKNetworkOperation *op = [self operationWithPath:@
"upload.php"
params:@{@
"Submit"
: @
"YES"
}
httpMethod:@
"POST"
];
[op addFile:file forKey:@
"image"
];
// setFreezable uploads your images after connection is restored!
[op setFreezable:YES];
[op addCompletionHandler:^(MKNetworkOperation* completedOperation) {
NSString *xmlString = [completedOperation responseString];
DLog(@
"%@"
, xmlString);
completionBlock(xmlString);
}
errorHandler:^(MKNetworkOperation *errorOp, NSError* error) {
errorBlock(error);
}];
[self enqueueOperation:op];
return
op;
}
|
上传的时候可以增加一个进度条,所以在调用这个方法的时候可以有以下代码。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
NSString *uploadPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingFormat:@
"/SampleImage.jpg"
];
self.uploadOperation = [ApplicationDelegate.testsEngine uploadImageFromFile:uploadPath
completionHandler:^(id twitPicURL) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@
"Uploaded to"
message:(NSString*) twitPicURL
delegate:nil
cancelButtonTitle:NSLocalizedString(@
"Dismiss"
, @
""
)
otherButtonTitles:nil];
[alert show];
self.uploadProgessBar.progress = 0.0;
}
errorHandler:^(NSError* error) {
[UIAlertView showWithError:error];
}];
[self.uploadOperation onUploadProgressChanged:^(
double
progress) {
DLog(@
"%.2f"
, progress*100.0);
self.uploadProgessBar.progress = progress;
}];
|
正确显示网络状态指示
正确显示网络状态指示的判断条件就是操作operation数大于0的时候。
自动改变队列大小
在wifi以及3G网络是会调用setMaxConcurrentOperationCount:方法切换最大操作数的大小。
自动缓存
MKNetWorkKit能够缓存你所有的GET请求,当请求相同时会调用本地缓存内容。
1
|
[self.yahooEngine useCache];
|
清空缓存使用如下方法
1
|
[ApplicationDelegate.yahooEngine emptyCache];
|
冻结网络操作
网络断开时的网络请求会被冻结,通过NSKeyedArchiver序列化在本地,当有网时会再次请求。MKNetworkOperation的setFreezable:方法就是冻结操作。
1
|
[op setFreezable:YES];
|
类似的请求只请求一个操作
就是同一个URL只请求一次。
图片缓存
MKNetworkEngine的imageAtURL:completionHandler:errorHandler:方法能够缓存图片。
1
2
3
4
|
[ApplicationDelegate.apiEngine imageAtURL:[NSURL URLWithString:(_strategyModel.titlepic)] completionHandler:^(UIImage* fetchedImage, NSURL* url,
BOOL
isInCache){
[iv setImage:fetchedImage];
}errorHandler:nil];
|
当然MKNetworkEngine的operationWithURLString: params: httpMethod:方法也可以请求图片,并且缓存,它其实就是根据一个URL地址来创建一个网络线程,然后把它加入到队列就可以了。
1
2
3
4
5
6
7
8
9
10
11
12
|
MKNetworkOperation *op1 =[ApplicationDelegate.apiEngine operationWithURLString:_strategyModel.titlepic params:nil httpMethod:nil];
[op1 addCompletionHandler:^(MKNetworkOperation *completedOperation) {
// [op1 responseImage];
[iv setImage:[completedOperation responseImage]];
} errorHandler:^(MKNetworkOperation *errorOp, NSError* error) {
}];
[ApplicationDelegate.apiEngine enqueueOperation:op1];
|
其实MKNetworkOperation有各种response数据,这里是responseImage,还有responseString、responseJSON、responseXML。
不过请求一个图片还可以使用MK提供的category,UIImageView+MKNetworkKitAdditions里面的方法,如下,不过我试了之后好像没有缓存,不过这个可以用于tableview上每个cell上显示的图片,比上面的要方便许多。
1
2
|
[self.thumbnailImage setImageFromURL:[NSURL URLWithString:self.loadingImageURLString]
placeHolderImage:nil];
|
缓存operation
其实每一个get请求都有缓存,要想知道你返回的数据是否缓存,可以用以下方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
[op addCompletionHandler:^(MKNetworkOperation *completedOperation)
{
// the completionBlock will be called twice.
// if you are interested only in new values, move that code within the else block
if
([completedOperation isCachedResponse]) {
DLog(@
"Data from cache %@"
, [completedOperation responseString]);
}
else
{
DLog(@
"Data from server %@"
, [completedOperation responseString]);
}
completionBlock([valueString doubleValue]);
}errorHandler:^(MKNetworkOperation *errorOp, NSError* error) {
errorBlock(error);
}];
|
下载文件
下载文件的时候也可以增加进度条,方法类似上面上传文件的使用,下载文件痛哟在操作上增加一个一个输出流,下载文件的实现可以如下。
1
2
3
4
5
6
7
8
9
10
|
-(MKNetworkOperation*) downloadFatAssFileFrom:(NSString*) remoteURL toFile:(NSString*) filePath {
MKNetworkOperation *op = [self operationWithURLString:remoteURL];
[op addDownloadStream:[NSOutputStream outputStreamToFileAtPath:filePath
append:YES]];
[self enqueueOperation:op];
return
op;
}
|