AFNetWorking初探之AFHTTPRequestOperation

原创 2015年11月19日 15:26:20

本文机遇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去暂停 或者取消请求。以后在细究吧。

相关文章推荐

AFNetWorking初探之AFHTTPRequestOperation(三)

关于AFHTTPRequestOperation 之前已经说说其使用方法,以及一些固定的包装初始化的操作,今天我们深入到setCompletionBlockWithSuccess看看它到底怎样的去回调...

APPStore上架应用支持IPV6的那些事, AFHTTPRequestOperation并非不能用了

APPStore上架应用支持IPV6的那些事, AFHTTPRequestOperation还可以用

AFNetworking3.0

  • 2016年04月25日 11:08
  • 118KB
  • 下载

AFNetworking2.5

  • 2015年03月24日 13:36
  • 283KB
  • 下载

基于AFNetWorking3.0的图片缓存分析

文/Yasin的简书(简书作者) 原文链接:http://www.jianshu.com/p/b1045c3fc8d0 著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。 图片在APP中...

AFNetworking 开源

  • 2012年11月02日 16:31
  • 166KB
  • 下载

AFNetworking (可以上传图片)

  • 2014年11月30日 16:54
  • 283KB
  • 下载

AFNetworking 批量上传统一返回图片的3种方法

AFNetworking 在去年年底升级到了 3.0。这个版本更新想必有很多好处,然而让我吃惊的是,它并没有 batch request 接口。之前的 1.x 版本、2.x 版本都实现了这个很常见的需...

AFNetworking三方库

  • 2016年05月10日 16:50
  • 79KB
  • 下载

最新版本的AFNetWorking

  • 2014年12月08日 10:55
  • 283KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:AFNetWorking初探之AFHTTPRequestOperation
举报原因:
原因补充:

(最多只允许输入30个字)