ASI基於CFNetwork框架開發,而AFN基於NSURL.
ASI更底層,請求使用創建CFHTTPMessageRef進行,使用NSOperationQueue進行管理,ASIHTTPRequest就是NSOpration的子類,並實現了NSCopy協議。使用static NSOperationQueue *sharedQueue, 在ASIHTTPRequest執行網絡請求時把自己加進去queue。
AFN基於NSURL,請求使用NSURLRequest作為參數傳入NSURlconnection進行。使用NSOperationQueue進行管理,通過初始化AFHTTPRquestOperationManager進行多線程管理。
更多可以參考 對比IOS網絡組件
2.優缺點對比
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];