[无限互联]AFNetworking核心类AFURLConnectionOperation的详解_第1页
[无限互联]AFNetworking核心类AFURLConnectionOperation的详解_第2页
[无限互联]AFNetworking核心类AFURLConnectionOperation的详解_第3页
[无限互联]AFNetworking核心类AFURLConnectionOperation的详解_第4页
[无限互联]AFNetworking核心类AFURLConnectionOperation的详解_第5页
已阅读5页,还剩13页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

无限互联AFNetworking核心类AFURLConnectionOperation的详解我们先看看AFURLConnectionOperation 作为AFNetworking最核心的类到底有什么神奇之处!1.线程先来看看 NSURLConnection 发送请求时的线程情况,NSURLConnection 是被设计成异步发送的,调用了start方法后,NSURLConnection 会新建一些线程用底层的 CFSocket 去发送和接收请求,在发送和接收的一些事件发生后通知原来线程的Runloop去回调事件。NSURLConnection 的同步方法 sendSynchronousRequest 方法也是基于异步的,同样要在其他线程去处理请求的发送和接收,只是同步方法会手动block住线程,发送状态的通知也不是通过 RunLoop 进行。NSURLConnection发送有以下三种方式 在主线程调异步接口 在子线程调同步接口 在子线程调异步接口AFNetworking使用的是最后一种方式方法,AFNetworking内部相关线程大致的关系如下图所示NSURLConnection是一个系统控件,所以我们可以把NSURLConnection当做一个黑盒,只管它的 start 和 callback 就行了。如果使用 AFHttpRequestOperationManager 的接口发送请求,这些请求会统一在一个 NSOperationQueue 里去发,所以多了上面 NSOperationQueue 的一个线程。相关代码:objc view plaincopyprint?1. /-线程- 2. /* 3. 子线程调用异步接口,子线程需要有 Runloop 去接收异步回调事件,这里也可以每个请求都新建一条 4. 带有 Runloop 的线程去侦听回调,但这一点好处都没有,既然是异步回调,除了处理回调内容,其他 5. 时间线程都是空闲可利用的,所有请求共用一个响应的线程就够了。 6. */ 7. /获取当前的NSRunLoop,子线程使用共同的Runloop 8. + (void)networkRequestThreadEntryPoint:(id)_unused object 9. autoreleasepool 10. NSThread currentThread setName:AFNetworking; 11. NSRunLoop *runLoop = NSRunLoop currentRunLoop; 12. runLoop addPort:NSMachPort port forMode:NSDefaultRunLoopMode; 13. runLoop run; 14. 15. 16. /创建新的子线程 17. + (NSThread *)networkRequestThread 18. static NSThread *_networkRequestThread = nil; 19. static dispatch_once_t oncePredicate; 20. dispatch_once(&oncePredicate, 21. _networkRequestThread = NSThread alloc initWithTarget:self selector:selector(networkRequestThreadEntryPoint:) object:nil; 22. _networkRequestThread start; 23. ); 24. return _networkRequestThread; 25. 26. /初始化NSURLConnection对象 27. - (instancetype)initWithRequest:(NSURLRequest *)urlRequest 28. NSParameterAssert(urlRequest); 29. self = super init; 30. if (!self) 31. return nil; 32. 33. _state = AFOperationReadyState; 34. self.lock = NSRecursiveLock alloc init; 35. = kAFNetworkingLockName; 36. self.runLoopModes = NSSet setWithObject:NSRunLoopCommonModes; 37. self.request = urlRequest; 38. self.shouldUseCredentialStorage = YES; 39. self.securityPolicy = AFSecurityPolicy defaultPolicy; 40. return self; 41. /-线程-/* 子线程调用异步接口,子线程需要有 Runloop 去接收异步回调事件,这里也可以每个请求都新建一条 带有 Runloop 的线程去侦听回调,但这一点好处都没有,既然是异步回调,除了处理回调内容,其他 时间线程都是空闲可利用的,所有请求共用一个响应的线程就够了。 */获取当前的NSRunLoop,子线程使用共同的Runloop+ (void)networkRequestThreadEntryPoint:(id)_unused object autoreleasepool NSThread currentThread setName:AFNetworking; NSRunLoop *runLoop = NSRunLoop currentRunLoop; runLoop addPort:NSMachPort port forMode:NSDefaultRunLoopMode; runLoop run; /创建新的子线程+ (NSThread *)networkRequestThread static NSThread *_networkRequestThread = nil; static dispatch_once_t oncePredicate; dispatch_once(&oncePredicate, _networkRequestThread = NSThread alloc initWithTarget:self selector:selector(networkRequestThreadEntryPoint:) object:nil; _networkRequestThread start; ); return _networkRequestThread;/初始化NSURLConnection对象- (instancetype)initWithRequest:(NSURLRequest *)urlRequest NSParameterAssert(urlRequest); self = super init; if (!self) return nil; _state = AFOperationReadyState; self.lock = NSRecursiveLock alloc init; = kAFNetworkingLockName; self.runLoopModes = NSSet setWithObject:NSRunLoopCommonModes; self.request = urlRequest; self.shouldUseCredentialStorage = YES; self.securityPolicy = AFSecurityPolicy defaultPolicy; return self;objc view plaincopyprint?1. /-线程- 2. /线程开始 3. - (void)start 4. /加锁,保护线程 5. self.lock lock; 6. if (self isCancelled) /取消线程 7. self performSelector:selector(cancelConnection) onThread:self class networkRequestThread withObject:nil waitUntilDone:NO modes:self.runLoopModes allObjects; 8. else if (self isReady) /线程已准备 9. self.state = AFOperationExecutingState; /将线程调为执行状态 10.11. self performSelector:selector(operationDidStart) onThread:self class networkRequestThread withObject:nil waitUntilDone:NO modes:self.runLoopModes allObjects; 12. 13. /线程执行完毕,解锁 14. self.lock unlock; 15. 16. /线程已开始 17. - (void)operationDidStart 18. self.lock lock; 19. if (!self isCancelled) 20. /创建链接对象 21. self.connection = NSURLConnection alloc initWithRequest:self.request delegate:self startImmediately:NO; 22. /获取当前的NSRunLoop,用来接收异步回调事件 23. NSRunLoop *runLoop = NSRunLoop currentRunLoop; 24. for (NSString *runLoopMode in self.runLoopModes) 25. /执行线程 26. self.connection scheduleInRunLoop:runLoop forMode:runLoopMode; 27. self.outputStream scheduleInRunLoop:runLoop forMode:runLoopMode; 28. 29. /开始链接 30. self.connection start; 31. 32. self.lock unlock; 33. /回到主线程,发送线程开始通知 34. dispatch_async(dispatch_get_main_queue(), 35. NSNotificationCenter defaultCenter postNotificationName:AFNetworkingOperationDidStartNotification object:self; 36. ); 37. 38. /线程完成 39. - (void)finish 40. self.lock lock; 41. self.state = AFOperationFinishedState; 42. self.lock unlock; 43. /发送通知,链接完成 44. dispatch_async(dispatch_get_main_queue(), 45. NSNotificationCenter defaultCenter postNotificationName:AFNetworkingOperationDidFinishNotification object:self; 46. ); 47. 48. /线程取消 49. - (void)cancel 50. self.lock lock; 51. if (!self isFinished & !self isCancelled) 52. super cancel; 53.54. if (self isExecuting) 55. self performSelector:selector(cancelConnection) onThread:self class networkRequestThread withObject:nil waitUntilDone:NO modes:self.runLoopModes allObjects; 56. 57. 58. self.lock unlock; 59. 60. /取消链接 61. - (void)cancelConnection 62. NSDictionary *userInfo = nil; 63. if (self.request URL) 64. userInfo = NSDictionary dictionaryWithObject:self.request URL forKey:NSURLErrorFailingURLErrorKey; 65. 66. NSError *error = NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorCancelled userInfo:userInfo; 67. if (!self isFinished) /处于链接状态,取消链接 68. if (self.connection) 69. /取消链接 70. self.connection cancel; 71. self performSelector:selector(connection:didFailWithError:) withObject:self.connection withObject:error; 72. else /链接完成,则直接结束 73. / Accomodate race condition where self.connection has not yet been set before cancellation 74. self.error = error; 75. self finish; 76. 77. 78. /-线程-/线程开始- (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;/线程已开始- (void)operationDidStart self.lock lock; if (!self isCancelled) /创建链接对象 self.connection = NSURLConnection alloc initWithRequest:self.request delegate:self startImmediately:NO; /获取当前的NSRunLoop,用来接收异步回调事件 NSRunLoop *runLoop = NSRunLoop currentRunLoop; for (NSString *runLoopMode in self.runLoopModes) /执行线程 self.connection scheduleInRunLoop:runLoop forMode:runLoopMode; self.outputStream scheduleInRunLoop:runLoop forMode:runLoopMode; /开始链接 self.connection start; self.lock unlock; /回到主线程,发送线程开始通知 dispatch_async(dispatch_get_main_queue(), NSNotificationCenter defaultCenter postNotificationName:AFNetworkingOperationDidStartNotification object:self; );/线程完成- (void)finish self.lock lock; self.state = AFOperationFinishedState; self.lock unlock; /发送通知,链接完成 dispatch_async(dispatch_get_main_queue(), NSNotificationCenter defaultCenter postNotificationName:AFNetworkingOperationDidFinishNotification object:self; );/线程取消- (void)cancel self.lock lock; if (!self isFinished & !self isCancelled) super cancel; if (self isExecuting) self performSelector:selector(cancelConnection) onThread:self class networkRequestThread withObject:nil waitUntilDone:NO modes:self.runLoopModes allObjects; self.lock unlock;/取消链接- (void)cancelConnection NSDictionary *userInfo = nil; if (self.request URL) userInfo = NSDictionary dictionaryWithObject:self.request URL forKey:NSURLErrorFailingURLErrorKey; NSError *error = NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorCancelled userInfo:userInfo; if (!self isFinished) /处于链接状态,取消链接 if (self.connection) /取消链接 self.connection cancel; self performSelector:selector(connection:didFailWithError:) withObject:self.connection withObject:error; else /链接完成,则直接结束 / Accomodate race condition where self.connection has not yet been set before cancellation self.error = error; self finish; 2.状态机继承 NSOperation 有个很麻烦的东西要处理,就是改变状态时需要发 KVO 通知,否则这个类加入 NSOperationQueue 不可用了。 NSOperationQueue 是用 KVO 方式侦听 NSOperation 状态的改变,以判断这个任务当前是否已完成,完成的任务需要在队列中除去并释放。AFURLConnectionOperation 对此做了个状态机,统一搞定状态切换以及发 KVO 通知的问题,内部要改变状态时,就只需要类似 self.state = AFOperationReadyState 的调用而不需要做其他了,状态改变的 KVO 通知在 setState 里发出。总的来说状态管理相关代码就三部分,一是限制一个状态可以切换到其他哪些状态,避免状态切换混乱,二是状态 Enum值 与 NSOperation 四个状态方法的对应,三是在 setState 时统一发 KVO 通知。相关代码如下:objc view plaincopyprint?1. /-状态机 2. /该方法的作用:状态 Enum值 与 NSOperation 四个状态方法的对应 3. static inline NSString * AFKeyPathFromOperationState(AFOperationState state) 4. switch (state) 5. case AFOperationReadyState: 6. return isReady; 7. case AFOperationExecutingState: 8. return isExecuting; 9. case AFOperationFinishedState: 10. return isFinished; 11. case AFOperationPausedState: 12. return isPaused; 13. default: 14. #pragma clang diagnostic push 15. #pragma clang diagnostic ignored -Wunreachable-code 16. return state; 17. #pragma clang diagnostic pop 18. 19. 20. 21. /NSOperation 状态的切换:限制一个状态可以切换到其他哪些状态,避免状态切换混乱 22. static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperationState toState, BOOL isCancelled) 23. switch (fromState) 24. case AFOperationReadyState: 25. switch (toState) 26. case AFOperationPausedState: 27. case AFOperationExecutingState: 28. return YES; 29. case AFOperationFinishedState: 30. return isCancelled; 31. default: 32. return NO; 33. 34. case AFOperationExecutingState: 35. switch (toState) 36. case AFOperationPausedState: 37. case AFOperationFinishedState: 38. return YES; 39. default: 40. return NO; 41. 42. case AFOperationFinishedState: 43. return NO; 44. case AFOperationPausedState: 45. return toState = AFOperationReadyState; 46. default: 47. #pragma clang diagnostic push 48. #pragma clang diagnostic ignored -Wunreachable-code 49. switch (toState) 50. case AFOperationPausedState: 51. case AFOperationReadyState: 52. case AFOperationExecutingState: 53. case AFOperationFinishedState: 54. return YES; 55. default: 56. return NO; 57. 58. 59. #pragma clang diagnostic pop 60. 61. /-状态机/该方法的作用:状态 Enum值 与 NSOperation 四个状态方法的对应static inline NSString * AFKeyPathFromOperationState(AFOperationState state) switch (state) case AFOperationReadyState: return isReady; case AFOperationExecutingState: return isExecuting; case AFOperationFinishedState: return isFinished; case AFOperationPausedState: return isPaused; default: #pragma clang diagnostic push#pragma clang diagnostic ignored -Wunreachable-code return state;#pragma clang diagnostic pop /NSOperation 状态的切换:限制一个状态可以切换到其他哪些状态,避免状态切换混乱static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperationState toState, BOOL isCancelled) switch (fromState) case AFOperationReadyState: switch (toState) case AFOperationPausedState: case AFOperationExecutingState: return YES; case AFOperationFinishedState: return isCancelled; default: return NO; case AFOperationExecutingState: switch (toState) case AFOperationPausedState: case AFOperationFinishedState: return YES; default: return NO; case AFOperationFinishedState: return NO; case AFOperationPausedState: return toState = AFOperationReadyState; default: #pragma clang diagnostic push#pragma clang diagnostic ignored -Wunreachable-code switch (toState) case AFOperationPausedState: case AFOperationReadyState: case AFOperationExecutingState: case AFOperationFinishedState: return YES; default: return NO; #pragma clang diagnostic pop objc view plaincopyprint?1. /-状态机 2. /NSOperationQueue 是用KVO方式侦听 NSOperation 状态的改变 3. /在该方法里统一发 KVO 通知给 NSOperationQueue,以判断这个任务当前是否已完成,完成的任务需要在队列中除去并释放。 4. - (void)setState:(AFOperationState)state 5. if (!AFStateTransitionIsValid(self.state, state, self isCancelled) 6. return; 7. 8. self.lock lock; 9. NSString *oldStateKey = AFKeyPathFromOperationState(self.state); 10. NSString *newStateKey = AFKeyPathFromOperationState(state); 11. self willChangeValueForKey:newStateKey; 12. self willChangeValueForKey:oldStateKey; 13. _state = state; 14. self didChangeValueForKey:oldStateKey; 15. self didChangeValueForKey:newStateKey; 16. self.lock unlock; 17. /-状态机/NSOperationQueue 是用KVO方式侦听 NSOperation 状态的改变/在该方法里统一发 KVO 通知给 NSOperationQueue,以判断这个任务当前是否已完成,完成的任务需要在队列中除去并释放。- (void)setState:(AFOperationState)state if (!AFStateTransitionIsValid(self.state, state, self isCancelled) return; self.lock lock; NSString *oldStateKey = AFKeyPathFromOperationState(self.state); NSString *newStateKey = AFKeyPathFromOperationState(state); self willChangeValueForKey:newStateKey; self willChangeValueForKey:oldStateKey; _state = state; self didChangeValueForKey:oldStateKey; self didChangeValueForKey:newStateKey; self.lock unlock;objc view plaincopyprint?1. 还有其他相关代码:-setState:, -isPaused:, -isReady:, -isExecuting:, -isFinished:. 还有其他相关代码:-setState:, -isPaused:, -isReady:, -isExecuting:, -isFinished:.3.NSURLConnectionDelegate处理 NSURLConnection Delegate 的内容不多,代码也是按请求回调的顺序排列下去,十分易读,主要流程就是接收到响应的时候打开 outputStream,接着有数据过来就往 outputStream 写,在上传/接收数据过程中会回调上层传进来的相应的callback,在请求完成回调到 connectionDidFinishLoading 时,关闭 outputStream,用 outputStream 组装 responseData 作为接收到的数据,把 NSOperation 状态设为 finished,表示任务完成,NSOperation 会自动调用 completeBlock,再回调到上层。相关代码如下:objc view plaincopyprint?1. /使用NSURLConnection时,用该方法检查证书的有效性 2. - (void)connection:(NSURLConnection *)connection 3. willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge /使用NSURLConnection时,用该方法检查证书的有效性- (void)connection:(NSURLConnection *)connectionwillSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challengeobjc view plaincopyprint?1. /* 2. connection: willSendRequest: redirectResponse: 3. 这个方法在请求将要被发送出去之前会调用 4. 返回值是一个NSURLRequest,就是那个真正将要被发送的请求 5. 第二个参数request就是被重定向处理过后的请求 6. 第三个参数redirectResponse是触发重定向请求的响应包.默认是支持跳转的。 7. */ 8. - (NSURLRequest *)connection:(NSURLConnection *)connection 9. willSendRequest:(NSURLRequest *)request 10. redirectResponse:(NSURLResponse *)redirectResponse 11. 12. if (self.redirectResponse) 13. return self.redirectResponse(connection, request, redirectResponse); 14. else 15. return request; 16. 17. 18. /上传数据 19. - (void)connection:(NSURLConnection _unused *)connection 20. didSendBodyData:(NSInteger)bytesWritten 21. totalBytesWritten:(NSInteger)totalBytesWritten 22. totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite 23. 24. /上传数据过程中回调上层传进来的相应的callback 25. if (self.uploadProgress) 26. dispatch_async(dispatch_get_main_queue(), 27. self.uploadProgress(NSUInteger)bytesWritten, totalBytesWritten, totalBytesExpectedToWrite); 28. ); 29. 30. 31. /代理对象接收到响应的时候打开 outputStream 32. - (void)connection:(NSURLConnection _unused *)connection 33. didReceiveRe

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论