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];

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM