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