本文机遇afnetworing2.* 3.0有些修改的地方,本人尚未探究。
首先先上代码,不想探究的可以直接复制粘切去使用了
-(void) getDataFromeNet:(NSString *)urlStr{
NSLog(@"get data from net:%@",urlStr);
//请求的url地址
NSURL *url=[NSURL URLWithString:[urlStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
//用NSURLRequest包装一下
NSURLRequest *requst = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10];
//AFHTTPRequestOperation包装一下
AFHTTPRequestOperation *op = [[AFHTTPRequestOperation alloc] initWithRequest:requst];
// 调用AFHTTPRequestOperation 的setCompletionBlockWithSuccess方法
[op setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *op,id responseObject){
NSString *jsonstr=op.responseString;
NSData *data=[jsonstr dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *dic=[NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSLog(@"NSDictionary%@",dic);
dataAarry = [dic objectForKey:@"zdBusinessList"];
// NSLog(@"获取到的数据为:%@",dataAarry);
NSLog(@"dataarray connt:%lu",(unsigned long)dataAarry.count);
if ([dataAarry count]<1) {
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"提示" message:@"没有相关数据" delegate:self cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
[alert show];
};
[self doneLoadingTableViewData];
}failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"发生错误!%@",error);
[self doneLoadingTableViewData];
}];
// 最后别忘了start
[op start];
}
首先先看这个方法
/*!
@method requestWithURL:cachePolicy:timeoutInterval:
@abstract Allocates and initializes a NSURLRequest with the given
URL and cache policy.
@param URL The URL for the request.
@param cachePolicy The cache policy for the request.
@param timeoutInterval The timeout interval for the request. See the
commentary for the <tt>timeoutInterval</tt> for more information on
timeout intervals.
@result A newly-created and autoreleased NSURLRequest instance.
*/
+ (instancetype)requestWithURL:(NSURL *)URL cachePolicy:(NSURLRequestCachePolicy)cachePolicy timeoutInterval:(NSTimeInterval)timeoutInterval;
NSURLRequest类为apple官方的类这个方法上看他的解释,此方法传递三个参数,
URL 不多说了 。
cachePolicy参数是 NSURLReQuestCachePolicy类型的 根缓存有关,感兴趣的可以去探究探究,这里不多说。一般使用NSURLRequestUseProtocolCachePolicy 。
timeoutInteval NSTimeInterval(typedef double NSTimeInterval)类型的 这个参数是为了设置请求超时时间,经常会用到。
然后再看这个方法
从.m文件中查看源码如下
- (instancetype)initWithRequest:(NSURLRequest *)urlRequest {
self = [super initWithRequest:urlRequest];//调用一个父类方法
if (!self) {
return nil;
}
self.responseSerializer = [AFHTTPResponseSerializer serializer]; //初始化一个responseSerializer AFHTTPResponseSerializer类型的
return self;
}
<span style="font-family: Arial, Helvetica, sans-serif;"> self = [super initWithRequest:urlRequest]</span>
调用父类的方法
现在想在.h中查看其使用说明,发现在.h中并没有这个方法。说明这个方法是重写了父类的方法。我们在去查他的父类发现这个
<span style="font-size:12px;">@interface AFHTTPRequestOperation : AFURLConnectionOperation</span>
<span style="font-size:12px;">@interface AFURLConnectionOperation : NSOperation <NSURLConnectionDelegate, NSURLConnectionDataDelegate, NSSecureCoding, NSCopying></span>
果然在在AFURLConnectionOperation 我们发现了这个方法 NSOperattion又回到了apple的文档当中不在细究。
/**
Initializes and returns a newly allocated operation object with a url connection configured with the specified url request.
This is the designated initializer.
@param urlRequest The request object to be used by the operation connection.
*/
- (instancetype)initWithRequest:(NSURLRequest *)urlRequest NS_DESIGNATED_INITIALIZER;
源码如下
- (instancetype)initWithRequest:(NSURLRequest *)urlRequest {
NSParameterAssert(urlRequest);
self = [super init];
if (!self) {
return nil;
}
_state = AFOperationReadyState;
self.lock = [[NSRecursiveLock alloc] init];//初始化了一个锁 估计跟进程同步有关
self.lock.name = kAFNetworkingLockName;
self.runLoopModes = [NSSet setWithObject:NSRunLoopCommonModes];
self.request = urlRequest;
self.shouldUseCredentialStorage = YES;
self.securityPolicy = [AFSecurityPolicy defaultPolicy];
return self;
}
上述一些初始化操作详细的以后补充。
再看
self.responseSerializer = [AFHTTPResponseSerializer serializer];
+ (instancetype)serializer {
return [[self alloc] init];
}
- (instancetype)init {
self = [super init];
if (!self) {
return nil;
}
self.stringEncoding = NSUTF8StringEncoding;//编码方式
self.acceptableStatusCodes = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(200, 100)];//成功的返回码,在这个范围内表示成功会调用成功回调
self.acceptableContentTypes = nil;
return self;
}
说了这么多其实上面都是一些初始化操作真正主角是下面的方法 他将用于我们请求成功后的处理情况。
- (void)setCompletionBlockWithSuccess:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure
{
// completionBlock is manually nilled out in AFURLConnectionOperation to break the retain cycle.
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-retain-cycles"
#pragma clang diagnostic ignored "-Wgnu"
self.completionBlock = ^{
if (self.completionGroup) {
dispatch_group_enter(self.completionGroup);
}
dispatch_async(http_request_operation_processing_queue(), ^{
if (self.error) {
if (failure) {
dispatch_group_async(self.completionGroup ?: http_request_operation_completion_group(), self.completionQueue ?: dispatch_get_main_queue(), ^{
failure(self, self.error);
});
}
} else {
id responseObject = self.responseObject;
if (self.error) {
if (failure) {
dispatch_group_async(self.completionGroup ?: http_request_operation_completion_group(), self.completionQueue ?: dispatch_get_main_queue(), ^{
failure(self, self.error);
});
}
} else {
if (success) {
dispatch_group_async(self.completionGroup ?: http_request_operation_completion_group(), self.completionQueue ?: dispatch_get_main_queue(), ^{
success(self, responseObject);
});
}
}
}
if (self.completionGroup) {
dispatch_group_leave(self.completionGroup);
}
});
};
#pragma clang diagnostic pop
}
源码很长,可以看到很多关于线程的操作,和各种block回调。反正我是看的云里雾里的,以后有机会细究吧。
具体说下block当中的两个参数
AFHTTPRequestOperation *op,id responseObject
op 也就是我们请求时自己包装的那个 AFHTTPRequestOperration 可以从中获取一些请求信息,常用的是返回码,笔者估计afnetworing中请求成功与否也是通过这里面的请求码来决定的。我们也可以在这里获取请求头信息。
主要的是这里:
NSString *jsonstr=op.responseString;
NSData *data=[jsonstr dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *dic=[NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
我们中op中获得数据然后自己去解析。
responseObject 这个事服务器给我们返回的数据 可以看到时ID类型的 这个在这里参数我们没有用到。其实这个参数在以后我们用AFHTTPRequestOperationManager的时候回给我们返回成一个解析好的对象,NSArray或者NSDictionnary 我们用起来会很方便,但是在这里笔者曾经打印过发现它并不是一个解析好的对象。我门职能从op中取出结果去自己解析。
最后看下
[op start];
- (void)start {
[self.lock lock];
if ([self isCancelled]) {
[self performSelector:@selector(cancelConnection) onThread:[[self class] networkRequestThread] withObject:nil waitUntilDone:NO modes:[self.runLoopModes allObjects]];
} else if ([self isReady]) {
self.state = AFOperationExecutingState;
[self performSelector:@selector(operationDidStart) onThread:[[self class] networkRequestThread] withObject:nil waitUntilDone:NO modes:[self.runLoopModes allObjects]];
}
[self.lock unlock];
}
可以看到为了保证原子性 在方法开始和结尾加入了锁 lock unlock 。这里我们也明白为甚么上述包装的方法中为什么会有一个对锁的初始化了。
看看源码还可以了解到这里有iscancellde isReady 不难猜出这里我们可以通过这个op去暂停 或者取消请求。以后在细究吧。