zoukankan      html  css  js  c++  java
  • IOS网络请求框架AFNetworking和ASIHttpRequest对比

    ASI基于CFNetwork框架开发,而AFN基于NSURL.

    ASI更底层,请求使用创建CFHTTPMessageRef进行,使用NSOperationQueue进行管理,ASIHTTPRequest就是NSOpration的子类,并实现了NSCopy协议。使用static NSOperationQueue *sharedQueue, 在ASIHTTPRequest执行网络请求时把自己加进去queue。

    AFN基于NSURL,请求使用NSURLRequest作为参数传入NSURlconnection进行。使用NSOperationQueue进行管理,通过初始化AFHTTPRquestOperationManager进行多线程管理。

    更多可以参考 对比IOS网络组件

    2.优缺点对比 

    选自: AFNetworking、MKNetworkKit和ASIHTTPRequest对比

    ASI开发者已于2012年10月宣布暂停该开源库的更新.

    AFN的活跃维护者比较多。

    3.使用 

    1.ASI的大概实现 

    ASIHTTPRequest是NSOperation的子类。 在ASIHTTPRequest有个初始方法:

    - (id)initWithURL:(NSURL *)newURL
    {
        self = [self init];
        [self setRequestMethod:@"GET"];
    
        [self setRunLoopMode:NSDefaultRunLoopMode];
        [self setShouldAttemptPersistentConnection:YES];
        [self setPersistentConnectionTimeoutSeconds:60.0];
        [self setShouldPresentCredentialsBeforeChallenge:YES];
        [self setShouldRedirect:YES];
        [self setShowAccurateProgress:YES];
        [self setShouldResetDownloadProgress:YES];
        [self setShouldResetUploadProgress:YES];
        [self setAllowCompressedResponse:YES];
        [self setShouldWaitToInflateCompressedResponses:YES];
        [self setDefaultResponseEncoding:NSISOLatin1StringEncoding];
        [self setShouldPresentProxyAuthenticationDialog:YES];
    
        [self setTimeOutSeconds:[ASIHTTPRequest defaultTimeOutSeconds]];
        [self setUseSessionPersistence:YES];
        [self setUseCookiePersistence:YES];
        [self setValidatesSecureCertificate:YES];
        [self setRequestCookies:[[[NSMutableArray alloc] init] autorelease]];
        [self setDidStartSelector:@selector(requestStarted:)];
        [self setDidReceiveResponseHeadersSelector:@selector(request:didReceiveResponseHeaders:)];
        [self setWillRedirectSelector:@selector(request:willRedirectToURL:)];
        [self setDidFinishSelector:@selector(requestFinished:)];
        [self setDidFailSelector:@selector(requestFailed:)];
        [self setDidReceiveDataSelector:@selector(request:didReceiveData:)];
        [self setURL:newURL];
        [self setCancelledLock:[[[NSRecursiveLock alloc] init] autorelease]];
        [self setDownloadCache:[[self class] defaultCache]];
        return self;
    }

    然后在执行异步网络访问时,把自己扔进shareQueue进行管理。

    - (void)startAsynchronous
    {
    #if DEBUG_REQUEST_STATUS || DEBUG_THROTTLING
        ASI_DEBUG_LOG(@"[STATUS] Starting asynchronous request %@",self);
    #endif
        [sharedQueue addOperation:self];
    }

    执行同步访问时更直接。注意[self main]. main方法里面执行了CFNetwork的操作。

    - (void)startSynchronous
    {
    #if DEBUG_REQUEST_STATUS || DEBUG_THROTTLING
        ASI_DEBUG_LOG(@"[STATUS] Starting synchronous request %@",self);
    #endif
        [self setSynchronous:YES];
        [self setRunLoopMode:ASIHTTPRequestRunLoopMode];
        [self setInProgress:YES];
    
        if (![self isCancelled] && ![self complete]) {
            [self main];
            while (!complete) {
                [[NSRunLoop currentRunLoop] runMode:[self runLoopMode] beforeDate:[NSDate distantFuture]];
            }
        }
    
        [self setInProgress:NO];
    }

    2.ASI基本使用 

    ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"XXXXX"]];
    [request setDelegate:self];   //ASIHTTPRequestDelegate
    [request startAsynchronous];

    不用进行很多配置,是因为ASIHTTPRequest的requestWithURL方法有默认配置,可以在实例化后自己再修改。如下(还有更多的自己阅读源码):

    [self setRequestMethod:@"GET"];   //访问方法
    
    [self setRunLoopMode:NSDefaultRunLoopMode];   //默认runloop
    [self setShouldAttemptPersistentConnection:YES];   //设置持久连接,重用request时用节约
    [self setPersistentConnectionTimeoutSeconds:60.0];
    [self setShouldPresentCredentialsBeforeChallenge:YES];  //是否要证书验证
    [self setShouldRedirect:YES];
    [self setShowAccurateProgress:YES];   //进度
    [self setShouldResetDownloadProgress:YES];   
    [self setShouldResetUploadProgress:YES];
    [self setAllowCompressedResponse:YES];
    [self setShouldWaitToInflateCompressedResponses:YES];
    [self setDefaultResponseEncoding:NSISOLatin1StringEncoding];
    [self setShouldPresentProxyAuthenticationDialog:YES];
    
    [self setTimeOutSeconds:[ASIHTTPRequest defaultTimeOutSeconds]];   //请求的网络等待时长
    [self setUseSessionPersistence:YES];    //保持session
    [self setUseCookiePersistence:YES];     //保持cookie
    [self setValidatesSecureCertificate:YES];
    [self setRequestCookies:[[[NSMutableArray alloc] init] autorelease]];
    [self setDidStartSelector:@selector(requestStarted:)];   //请求开始
    [self setDidReceiveResponseHeadersSelector:@selector(request:didReceiveResponseHeaders:)];        //获取到ResponseHeader
    [self setWillRedirectSelector:@selector(request:willRedirectToURL:)];
    [self setDidFinishSelector:@selector(requestFinished:)];    //请求完成
    [self setDidFailSelector:@selector(requestFailed:)];      //请求失败
    [self setDidReceiveDataSelector:@selector(request:didReceiveData:)];   //获取到data,多次
    [self setURL:newURL];      //设置URL
    [self setCancelledLock:[[[NSRecursiveLock alloc] init] autorelease]];
    [self setDownloadCache:[[self class] defaultCache]];

    ASIHTTPRequestDelegate的代理:

    - (void)requestStarted:(ASIHTTPRequest *)request;
    - (void)request:(ASIHTTPRequest *)request didReceiveResponseHeaders:(NSDictionary *)responseHeaders;
    - (void)request:(ASIHTTPRequest *)request willRedirectToURL:(NSURL *)newURL;
    - (void)requestFinished:(ASIHTTPRequest *)request;
    - (void)requestFailed:(ASIHTTPRequest *)request;
    - (void)requestRedirected:(ASIHTTPRequest *)request;
    
    - (void)request:(ASIHTTPRequest *)request didReceiveData:(NSData *)data;
    
    - (void)authenticationNeededForRequest:(ASIHTTPRequest *)request;
    - (void)proxyAuthenticationNeededForRequest:(ASIHTTPRequest *)request;

    2.AFN基本使用 

    1.实现基本原理: 

    先看看AFHTTPRquestOperationManager的默认初始化方法:可以看出默认的request为二进制,reponse为json解析。可以根据业务进行修改。 

    - (instancetype)initWithBaseURL:(NSURL *)url {
        self = [super init];
        if (!self) {
            return nil;
        }
    
        // Ensure terminal slash for baseURL path, so that NSURL +URLWithString:relativeToURL: works as expected
        if ([[url path] length] > 0 && ![[url absoluteString] hasSuffix:@"/"]) {
            url = [url URLByAppendingPathComponent:@""];
        }
    
        self.baseURL = url;     //初始化了baseurl,比如你的访问地址是http://192.168.0.100/login.action . 初始化baseUrl为http://192.168.0.100/ , 以后manager GET:@"login.action"即可。
    
        self.requestSerializer = [AFHTTPRequestSerializer serializer];  
        self.responseSerializer = [AFJSONResponseSerializer serializer];
    
        self.securityPolicy = [AFSecurityPolicy defaultPolicy]; //AFSSLPinningModeNone无隐私要求
    
        self.reachabilityManager = [AFNetworkReachabilityManager sharedManager];
    
        self.operationQueue = [[NSOperationQueue alloc] init];
    
        self.shouldUseCredentialStorage = YES;
    
        return self;
    }

    再看看其中一个方法GET方法。

    AFHTTPRequestOperation 是 AFURLConnectionOperation的子类,AFURLConnectionOperation的子类是NSOperation的子类,并实现了NSURLConnectionDelegate等网络协议。

    @interface AFURLConnectionOperation : NSOperation <NSURLConnectionDelegate, NSURLConnectionDataDelegate, NSSecureCoding, NSCopying>

    是使用刚才manager初始化生成的operationQueue进行多线程管理,所以一个项目有一个manager然后用来管理网络请求就行了。多线程已经由AFN内部处理了。

    - (AFHTTPRequestOperation *)GET:(NSString *)URLString
                         parameters:(id)parameters
                            success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
                            failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure
    {
        AFHTTPRequestOperation *operation = [self HTTPRequestOperationWithHTTPMethod:@"GET" URLString:URLString parameters:parameters success:success failure:failure];
    
        [self.operationQueue addOperation:operation];
        return operation;
    }

    AFHTTPRequestOperation的生成,复用了很多manager的属性:

    - (AFHTTPRequestOperation *)HTTPRequestOperationWithRequest:(NSURLRequest *)request
                                                        success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
                                                        failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure
    {
        AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
        operation.responseSerializer = self.responseSerializer;
        operation.shouldUseCredentialStorage = self.shouldUseCredentialStorage;
        operation.credential = self.credential;
        operation.securityPolicy = self.securityPolicy;
    
        [operation setCompletionBlockWithSuccess:success failure:failure];  //注意这个地方
        operation.completionQueue = self.completionQueue;
        operation.completionGroup = self.completionGroup;
    
        return operation;
    }

    最后的回调,AFN是使用了NSOperation自己的block,难怪在协议找了好久没找到

    - (void)setCompletionBlock:(void (^)(void))block {
        [self.lock lock];
        if (!block) {
            [super setCompletionBlock:nil];
        } else {
            __weak __typeof(self)weakSelf = self;
            [super setCompletionBlock:^ {
                __strong __typeof(weakSelf)strongSelf = weakSelf;
    
    #pragma clang diagnostic push
    #pragma clang diagnostic ignored "-Wgnu"
                dispatch_group_t group = strongSelf.completionGroup ?: url_request_operation_completion_group();
                dispatch_queue_t queue = strongSelf.completionQueue ?: dispatch_get_main_queue();
    #pragma clang diagnostic pop
    
                dispatch_group_async(group, queue, ^{
                    block();
                });
    
                dispatch_group_notify(group, url_request_operation_completion_queue(), ^{
                    [strongSelf setCompletionBlock:nil];
                });
            }];
        }
        [self.lock unlock];
    }

    2.基本GET 

    AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
        [manager GET:@"http://example.com/resources.json" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
            NSLog(@"JSON: %@", responseObject);
        } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
            NSLog(@"Error: %@", error);
        }];

    3.下载一个文件 

    NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
    AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
    
    NSURL *URL = [NSURL URLWithString:@"http://example.com/download.zip"];
    NSURLRequest *request = [NSURLRequest requestWithURL:URL];
    
    NSURLSessionDownloadTask *downloadTask = [manager downloadTaskWithRequest:request progress:nil destination:^NSURL *(NSURL *targetPath, NSURLResponse *response) {
        NSURL *documentsDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:NO error:nil];
        return [documentsDirectoryURL URLByAppendingPathComponent:[response suggestedFilename]];
    } completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error) {
        NSLog(@"File downloaded to: %@", filePath);
    }];
    [downloadTask resume];
     
  • 相关阅读:
    使用jquery插件validate制作的表单验证案例
    POJ2992:Divisors(求N!因子的个数,乘性函数,分解n!的质因子(算是找规律))
    HDU1695:GCD(容斥原理+欧拉函数+质因数分解)好题
    HDU4135Co-prime(容斥原理)
    HDU1796How many integers can you find(容斥原理)
    Miller-Rabin素数测试算法(POJ1811Prime Test)
    乘法逆元+模的运算规则
    因子和与因子个数 (乘性函数)
    费马小定理的证明:
    整数(质因子)分解(Pollard rho大整数分解)
  • 原文地址:https://www.cnblogs.com/fengmin/p/5826637.html
Copyright © 2011-2022 走看看