上一篇我們了解了AFNetworking各個(gè)模塊的功能,今天我們來了解一下AFNetworking源碼的實(shí)現(xiàn)
我們先看看AFURLConnectionOperation 作為AFNetworking最核心的類到底有什么神奇之處溪椎!
1.線程
先來看看 NSURLConnection 發(fā)送請求時(shí)的線程情況普舆,NSURLConnection 是被設(shè)計(jì)成異步發(fā)送的,調(diào)用了start方法后校读,NSURLConnection 會新建一些線程用底層的 CFSocket 去發(fā)送和接收請求沼侣,在發(fā)送和接收的一些事件發(fā)生后通知原來線程的Runloop去回調(diào)事件。
NSURLConnection 的同步方法 sendSynchronousRequest 方法也是基于異步的歉秫,同樣要在其他線程去處理請求的發(fā)送和接收蛾洛,只是同步方法會手動block住線程,發(fā)送狀態(tài)的通知也不是通過 RunLoop 進(jìn)行雁芙。
NSURLConnection發(fā)送有以下三種方式
? 在主線程調(diào)異步接口
? 在子線程調(diào)同步接口
? 在子線程調(diào)異步接口
AFNetworking使用的是最后一種方式方法轧膘,AFNetworking內(nèi)部相關(guān)線程大致的關(guān)系如下圖所示
NSURLConnection是一個(gè)系統(tǒng)控件,所以我們可以把NSURLConnection當(dāng)做一個(gè)黑盒却特,只管它的 start 和 callback 就行了扶供。如果使用 AFHttpRequestOperationManager 的接口發(fā)送請求,這些請求會統(tǒng)一在一個(gè) NSOperationQueue 里去發(fā)裂明,所以多了上面 NSOperationQueue 的一個(gè)線程椿浓。
相關(guān)代碼:
[objc] view plaincopy
1. //-------------------------線程--------------------
2. /*
3. 子線程調(diào)用異步接口太援,子線程需要有 Runloop 去接收異步回調(diào)事件,這里也可以每個(gè)請求都新建一條
4. 帶有 Runloop 的線程去偵聽回調(diào)扳碍,但這一點(diǎn)好處都沒有提岔,既然是異步回調(diào),除了處理回調(diào)內(nèi)容笋敞,其他
5. 時(shí)間線程都是空閑可利用的碱蒙,所有請求共用一個(gè)響應(yīng)的線程就夠了。
6. */
7. //獲取當(dāng)前的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. //創(chuàng)建新的子線程
17. + (NSThread *)networkRequestThread {
18. <span style="white-space:pre"> </span> static NSThread *_networkRequestThread = nil;
19. <span style="white-space:pre"> </span> static dispatch_once_t oncePredicate;
20. <span style="white-space:pre"> </span> dispatch_once(&oncePredicate, ^{
21. <span style="white-space:pre"> </span> _networkRequestThread = [[NSThread alloc] initWithTarget:self selector:@selector(networkRequestThreadEntryPoint:) object:nil];
22. <span style="white-space:pre"> </span> [_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. self.lock.name = kAFNetworkingLockName;
36. self.runLoopModes = [NSSet setWithObject:NSRunLoopCommonModes];
37. self.request = urlRequest;
38. self.shouldUseCredentialStorage = YES;
39. self.securityPolicy = [AFSecurityPolicy defaultPolicy];
40. return self;
41. }
[objc] view plaincopy
1. //------------------------線程--------------------
2. //線程開始
3. - (void)start {
4. //加鎖赛惩,保護(hù)線程
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]) { //線程已準(zhǔn)備
9. self.state = AFOperationExecutingState; //將線程調(diào)為執(zhí)行狀態(tài)
10.
11. [self performSelector:@selector(operationDidStart) onThread:[[self class] networkRequestThread] withObject:nil waitUntilDone:NO modes:[self.runLoopModes allObjects]];
12. }
13. //線程執(zhí)行完畢,解鎖
14. [self.lock unlock];
15. }
16. //線程已開始
17. - (void)operationDidStart {
18. [self.lock lock];
19. if (![self isCancelled]) {
20. //創(chuàng)建鏈接對象
21. self.connection = [[NSURLConnection alloc] initWithRequest:self.request delegate:self startImmediately:NO];
22. //獲取當(dāng)前的NSRunLoop趁餐,用來接收異步回調(diào)事件
23. NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
24. for (NSString *runLoopMode in self.runLoopModes) {
25. //執(zhí)行線程
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. //回到主線程喷兼,發(fā)送線程開始通知
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. //發(fā)送通知,鏈接完成
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]) { //處于鏈接狀態(tài)后雷,取消鏈接
68. if (self.connection) {
69. //取消鏈接
70. [self.connection cancel];
71. [self performSelector:@selector(connection:didFailWithError:) withObject:self.connection withObject:error];
72. } else { //鏈接完成季惯,則直接結(jié)束
73. // Accomodate race condition where `self.connection` has not yet been set before cancellation
74. self.error = error;
75. [self finish];
76. }
77. }
78. }
2.狀態(tài)機(jī)
繼承 NSOperation 有個(gè)很麻煩的東西要處理,就是改變狀態(tài)時(shí)需要發(fā) KVO 通知臀突,否則這個(gè)類加入 NSOperationQueue 不可用了勉抓。 NSOperationQueue 是用 KVO 方式偵聽 NSOperation 狀態(tài)的改變,以判斷這個(gè)任務(wù)當(dāng)前是否已完成候学,完成的任務(wù)需要在隊(duì)列中除去并釋放藕筋。
AFURLConnectionOperation 對此做了個(gè)狀態(tài)機(jī),統(tǒng)一搞定狀態(tài)切換以及發(fā) KVO 通知的問題梳码,內(nèi)部要改變狀態(tài)時(shí)念逞,就只需要類似 self.state = AFOperationReadyState 的調(diào)用而不需要做其他了,狀態(tài)改變的 KVO 通知在 setState 里發(fā)出边翁。
總的來說狀態(tài)管理相關(guān)代碼就三部分,一是限制一個(gè)狀態(tài)可以切換到其他哪些狀態(tài)硕盹,避免狀態(tài)切換混亂符匾,二是狀態(tài) Enum值 與 NSOperation 四個(gè)狀態(tài)方法的對應(yīng),三是在 setState 時(shí)統(tǒng)一發(fā) KVO 通知瘩例。
相關(guān)代碼如下:
[objc] view plaincopy
1. //-------------------------狀態(tài)機(jī)
2. //該方法的作用:狀態(tài) Enum值 與 NSOperation 四個(gè)狀態(tài)方法的對應(yīng)
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 狀態(tài)的切換:限制一個(gè)狀態(tài)可以切換到其他哪些狀態(tài)啊胶,避免狀態(tài)切換混亂
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. }
[objc] view plaincopy
1. //-------------------------狀態(tài)機(jī)
2. //NSOperationQueue 是用KVO方式偵聽 NSOperation 狀態(tài)的改變
3. //在該方法里統(tǒng)一發(fā) KVO 通知給 NSOperationQueue,以判斷這個(gè)任務(wù)當(dāng)前是否已完成垛贤,完成的任務(wù)需要在隊(duì)列中除去并釋放焰坪。
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. }
[objc] view plaincopy
- 還有其他相關(guān)代碼:-setState:, -isPaused:, -isReady:, -isExecuting:, -isFinished:.
3.NSURLConnectionDelegate
處理 NSURLConnection Delegate 的內(nèi)容不多,代碼也是按請求回調(diào)的順序排列下去聘惦,十分易讀某饰,主要流程就是接收到響應(yīng)的時(shí)候打開 outputStream,接著有數(shù)據(jù)過來就往 outputStream 寫,在上傳/接收數(shù)據(jù)過程中會回調(diào)上層傳進(jìn)來的相應(yīng)的callback黔漂,在請求完成回調(diào)到 connectionDidFinishLoading 時(shí)诫尽,關(guān)閉 outputStream,用 outputStream 組裝 responseData 作為接收到的數(shù)據(jù)炬守,把 NSOperation 狀態(tài)設(shè)為 finished牧嫉,表示任務(wù)完成,NSOperation 會自動調(diào)用 completeBlock减途,再回調(diào)到上層酣藻。
相關(guān)代碼如下:
[objc] view plaincopy
1. //使用NSURLConnection時(shí),用該方法檢查證書的有效性
2. - (void)connection:(NSURLConnection *)connection
3. willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge{}
[objc] view plaincopy
1. /*
2. connection: willSendRequest: redirectResponse:
3. 這個(gè)方法在請求將要被發(fā)送出去之前會調(diào)用
4. 返回值是一個(gè)NSURLRequest,就是那個(gè)真正將要被發(fā)送的請求
5. 第二個(gè)參數(shù)request就是被重定向處理過后的請求
6. 第三個(gè)參數(shù)<span style="font-family: Arial, Helvetica, sans-serif;">redirectResponse</span><span style="font-family: Arial, Helvetica, sans-serif;">是觸發(fā)重定向請求的響應(yīng)包.默認(rèn)是支持跳轉(zhuǎn)的鳍置。</span>
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. //上傳數(shù)據(jù)
19. - (void)connection:(NSURLConnection __unused *)connection
20. didSendBodyData:(NSInteger)bytesWritten
21. totalBytesWritten:(NSInteger)totalBytesWritten
22. totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite
23. {
24. //上傳數(shù)據(jù)過程中回調(diào)上層傳進(jìn)來的相應(yīng)的callback
25. if (self.uploadProgress) {
26. dispatch_async(dispatch_get_main_queue(), ^{
27. self.uploadProgress((NSUInteger)bytesWritten, totalBytesWritten, totalBytesExpectedToWrite);
28. });
29. }
30. }
31. //代理對象接收到響應(yīng)的時(shí)候打開 outputStream
32. - (void)connection:(NSURLConnection __unused *)connection
33. didReceiveResponse:(NSURLResponse *)response
34. {
35. self.response = response;
36. [self.outputStream open];
37. }
38. //有數(shù)據(jù)過來時(shí)辽剧,往outputStream寫數(shù)據(jù)
39. - (void)connection:(NSURLConnection __unused *)connection
40. didReceiveData:(NSData *)data
41. {
42. NSUInteger length = [data length];
43. while (YES) {
44. NSInteger totalNumberOfBytesWritten = 0;
45. if ([self.outputStream hasSpaceAvailable]) {
46. const uint8_t *dataBuffer = (uint8_t *)[data bytes];
47. NSInteger numberOfBytesWritten = 0;
48. while (totalNumberOfBytesWritten < (NSInteger)length) {
49. numberOfBytesWritten = [self.outputStream write:&dataBuffer[(NSUInteger)totalNumberOfBytesWritten] maxLength:(length - (NSUInteger)totalNumberOfBytesWritten)];
50. if (numberOfBytesWritten == -1) {
51. break;
52. }
53. totalNumberOfBytesWritten += numberOfBytesWritten;
54. }
55. break;
56. }
57. if (self.outputStream.streamError) {
58. [self.connection cancel];
59. [self performSelector:@selector(connection:didFailWithError:) withObject:self.connection withObject:self.outputStream.streamError];
60. return;
61. }
62. }
63. //接收數(shù)據(jù)過程中會回調(diào)上層傳進(jìn)來的相應(yīng)的callback
64. dispatch_async(dispatch_get_main_queue(), ^{
65. self.totalBytesRead += (long long)length;
66.
67. if (self.downloadProgress) {
68. self.downloadProgress(length, self.totalBytesRead, self.response.expectedContentLength);
69. }
70. });
71. }
72. //請求完成回調(diào)到 connectionDidFinishLoading 時(shí),關(guān)閉 outputStream
73. //用 outputStream 組裝 responseData 作為接收到的數(shù)據(jù)墓捻,把 NSOperation 狀態(tài)設(shè)為 finished抖仅,表示任務(wù)完成
74. - (void)connectionDidFinishLoading:(NSURLConnection __unused *)connection {
75. self.responseData = [self.outputStream propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
76. [self.outputStream close];
77. if (self.responseData) {
78. self.outputStream = nil;
79. }
80. self.connection = nil;
81. [self finish];
82. }
4.setCompleteBlock
AFNetworking重寫NSOperation提供的setCompletionBlock,用于任務(wù)完成時(shí)回調(diào)傳進(jìn)來的block砖第,并且實(shí)現(xiàn)消除循環(huán)引用撤卢。
在 NSOperation 的實(shí)現(xiàn)里,completionBlock 是 NSOperation 對象的一個(gè)成員梧兼,NSOperation 對象持有著 completionBlock放吩,若傳進(jìn)來的 block 用到了 NSOperation 對象,或者 block 用到的對象持有了這個(gè) NSOperation 對象羽杰,就會造成循環(huán)引用渡紫。這里執(zhí)行完 block 后調(diào)用 [strongSelf setCompletionBlock:nil] 把 completionBlock 設(shè)成 nil,手動釋放 self(NSOperation對象) 持有的 completionBlock 對象考赛,打破循環(huán)引用惕澎。
相關(guān)代碼如下:
[objc] view plaincopy
1. <span style="font-size:14px;">//任務(wù)完成,回調(diào)block
2. - (void)setCompletionBlock:(void (^)(void))block {
3. [self.lock lock];
4. if (!block) {
5. [super setCompletionBlock:nil];
6. } else {
7. //weakSelf是為了block不持有self颜骤,避免循環(huán)引用
8. __weak __typeof(self)weakSelf = self;
9. [super setCompletionBlock:^ {
10. //再聲明一個(gè)strongSelf是因?yàn)橐坏┻M(jìn)入block執(zhí)行唧喉,就不允許self在這個(gè)執(zhí)行過程中釋放。block執(zhí)行完后這個(gè)strongSelf會自動釋放忍抽,沒有循環(huán)引用問題八孝。
11. __strong __typeof(weakSelf)strongSelf = weakSelf;
12. #pragma clang diagnostic push
13. #pragma clang diagnostic ignored "-Wgnu"
14. dispatch_group_t group = strongSelf.completionGroup ?: url_request_operation_completion_group();
15. dispatch_queue_t queue = strongSelf.completionQueue ?: dispatch_get_main_queue();
16. #pragma clang diagnostic pop
17. dispatch_group_async(group, queue, ^{
18. //傳入一個(gè) block 作為任務(wù)執(zhí)行完成時(shí)(state狀態(tài)機(jī)變?yōu)閒inished時(shí))的回調(diào)
19. block();
20. });
21. /*
22. 循環(huán)引用:NSOperation持有completionBlock,若傳進(jìn)來的block 用到了 NSOperation 對象鸠项,
23. 或者 block 用到的對象持有了這個(gè) NSOperation 對象干跛,就會造成循環(huán)引用
24. 解決方法:
25. 消除循環(huán)引用,手動釋放 self(NSOperation對象) 持有的 completionBlock 對象,打破循環(huán)引用
26. */
27. dispatch_group_notify(group, url_request_operation_completion_queue(), ^{
28. [strongSelf setCompletionBlock:nil];
29. });
30. }];
31. }
32. [self.lock unlock];
33. }</span>
5.batchOfRequestOperations
這里額外提供了一個(gè)便捷接口祟绊,可以傳入一組請求楼入,在所有請求完成后回調(diào) complionBlock哥捕,在每一個(gè)請求完成時(shí)回調(diào) progressBlock 通知外面有多少個(gè)請求已完成
[objc] view plaincopy
1. <span style="font-size:14px;">+ (NSArray *)batchOfRequestOperations:(NSArray *)operations
2. progressBlock:(void (^)(NSUInteger numberOfFinishedOperations, NSUInteger totalNumberOfOperations))progressBlock
3. completionBlock:(void (^)(NSArray *operations))completionBlock
4. {
5. //請求不存在,或者請求數(shù)為0浅辙,返回
6. if (!operations || [operations count] == 0) {
7. return @[[NSBlockOperation blockOperationWithBlock:^{
8. dispatch_async(dispatch_get_main_queue(), ^{
9. if (completionBlock) {
10. completionBlock(@[]);
11. }
12. });
13. }]];
14. }
15. __block dispatch_group_t group = dispatch_group_create();
16. //任務(wù)數(shù)為0時(shí)執(zhí)行dispatch_group_notify的內(nèi)容
17. NSBlockOperation *batchedOperation = [NSBlockOperation blockOperationWithBlock:^{
18. dispatch_group_notify(group, dispatch_get_main_queue(), ^{
19. if (completionBlock) {
20. completionBlock(operations);
21. }
22. });
23. }];
24. //取出每一個(gè)請求(任務(wù))
25. for (AFURLConnectionOperation *operation in operations) {
26. operation.completionGroup = group;
27. void (^originalCompletionBlock)(void) = [operation.completionBlock copy];
28. __weak __typeof(operation)weakOperation = operation;
29. operation.completionBlock = ^{
30. __strong __typeof(weakOperation)strongOperation = weakOperation;
31. #pragma clang diagnostic push
32. #pragma clang diagnostic ignored "-Wgnu"
33. dispatch_queue_t queue = strongOperation.completionQueue ?: dispatch_get_main_queue();
34. #pragma clang diagnostic pop
35. //異步執(zhí)行任務(wù)
36. dispatch_group_async(group, queue, ^{
37. if (originalCompletionBlock) {
38. //任務(wù)完成后回調(diào)block
39. originalCompletionBlock();
40. }
41. NSUInteger numberOfFinishedOperations = [[operations indexesOfObjectsPassingTest:^BOOL(id op, NSUInteger __unused idx, BOOL __unused *stop) {
42. return [op isFinished];
43. }] count];
44.
45. //在每一個(gè)請求完成時(shí)回調(diào) progressBlock 通知外面有多少個(gè)請求已完成扭弧。
46. if (progressBlock) {
47. progressBlock(numberOfFinishedOperations, [operations count]);
48. }
49.
50. dispatch_group_leave(group); //類似release,任務(wù)數(shù)-1
51. });
52. };
53. dispatch_group_enter(group); //類似retain记舆,任務(wù)數(shù)+1
54. [batchedOperation addDependency:operation];
55. }
56. return [operations arrayByAddingObject:batchedOperation];
57. }</span>
6.鎖鸽捻、序列化、backgroundTask
鎖 :AFURLConnectionOperation 有一把遞歸鎖泽腮,在所有會訪問/修改成員變量的對外接口都加了鎖御蒲,因?yàn)檫@些對外的接口用戶是可以在任意線程調(diào)用的,對于訪問和修改成員變量的接口诊赊,必須用鎖保證線程安全厚满。
序列化:AFNetworking 的多數(shù)類都支持序列化,實(shí)現(xiàn)的是 NSSecureCoding 的接口碧磅,用 -decodeObjectOfClass:forKey: 方法碘箍,指定 Class保證序列化后的數(shù)據(jù)不被篡改,若不指定 Class鲸郊,-decode 出來的對象可能不是原來的對象丰榴,有潛在風(fēng)險(xiǎn)。
backgroundTask:這里提供了setShouldExecuteAsBackgroundTaskWithExpirationHandler 接口秆撮,決定APP進(jìn)入后臺后是否繼續(xù)發(fā)送接收請求四濒,并在后臺執(zhí)行時(shí)間超時(shí)后取消所有請求。在 dealloc 里需要調(diào)用 [application endBackgroundTask:] 职辨,告訴系統(tǒng)這個(gè)后臺任務(wù)已經(jīng)完成盗蟆,不然系統(tǒng)會一直讓你的APP運(yùn)行在后臺,直到超時(shí)舒裤。
7.AFHTTPRequestOperation
AFHTTPRequestOperation 繼承了 AFURLConnectionOperation喳资,實(shí)現(xiàn)的功能比較少,主要多了responseSerializer腾供,暫停下載斷點(diǎn)續(xù)傳骨饿,以及提供接口請求成功失敗的回調(diào)接口。
理解了AFURLConnectionOperation台腥,就會覺得AFHTTPRequestOperation比較簡單,所以具體的就不寫了绒北。
- (void)setCompletionBlockWithSuccess:(void (^)(AFHTTPRequestOperation *operation,idresponseObject))success
failure:(void (^)(AFHTTPRequestOperation *operation,NSError *error))failure;
8.AFHTTPRequestOperationManager
AFHTTPRequestOperationManager封裝了AFNetworking其他功能的各個(gè)模塊黎侈,如AFHTTPRequestSerializer(請求序列化),
AFHTTPResponseSerializer(響應(yīng)序列化)闷游,
AFSecurityPolicy(安全策略)峻汉,
AFNetworkReachabilityManager(可達(dá)性)贴汪,
封裝了HTTP請求所相關(guān)的代碼
并且將所有的請求添加到同一個(gè)NSOperationQueue請求隊(duì)列里。
并且封裝 HTTP 請求的常見方式休吠,GET / POST / PUT / DELETE / PATCH……
NSURLConnection相關(guān)的代碼就解析到這里扳埂。下一篇講AFNetworking其他功能模塊!