版本記錄
版本號 | 時間 |
---|---|
V1.0 | 2018.03.04 |
前言
我們做APP發(fā)起網(wǎng)絡(luò)請求迟赃,都離不開一個非常有用的框架AFNetworking诈闺,可以說這個框架的知名度已經(jīng)超過了蘋果的底層網(wǎng)絡(luò)請求部分渴庆,很多人可能不知道蘋果底層是如何發(fā)起網(wǎng)絡(luò)請求的,但是一定知道
AFNetworking
,接下來幾篇我們就一起詳細(xì)的解析一下這個框架襟雷。感興趣的可以看上面寫的幾篇刃滓。
1. AFNetworking源碼探究(一) —— 基本介紹
2. AFNetworking源碼探究(二) —— GET請求實現(xiàn)之NSURLSessionDataTask實例化(一)
3. AFNetworking源碼探究(三) —— GET請求實現(xiàn)之任務(wù)進(jìn)度設(shè)置和通知監(jiān)聽(一)
4. AFNetworking源碼探究(四) —— GET請求實現(xiàn)之代理轉(zhuǎn)發(fā)思想(一)
5. AFNetworking源碼探究(五) —— AFURLSessionManager中NSURLSessionDelegate詳細(xì)解析(一)
6. AFNetworking源碼探究(六) —— AFURLSessionManager中NSURLSessionTaskDelegate詳細(xì)解析(一)
7. AFNetworking源碼探究(七) —— AFURLSessionManager中NSURLSessionDataDelegate詳細(xì)解析(一)
8. AFNetworking源碼探究(八) —— AFURLSessionManager中NSURLSessionDownloadDelegate詳細(xì)解析(一)
9. AFNetworking源碼探究(九) —— AFURLSessionManagerTaskDelegate中三個轉(zhuǎn)發(fā)代理方法詳細(xì)解析(一)
10. AFNetworking源碼探究(十) —— 數(shù)據(jù)解析之?dāng)?shù)據(jù)解析架構(gòu)的分析(一)
11. AFNetworking源碼探究(十一) —— 數(shù)據(jù)解析之子類中協(xié)議方法的實現(xiàn)(二)
12. AFNetworking源碼探究(十二) —— 數(shù)據(jù)解析之子類中協(xié)議方法的實現(xiàn)(三)
13. AFNetworking源碼探究(十三) —— AFSecurityPolicy與安全認(rèn)證 (一)
14. AFNetworking源碼探究(十四) —— AFSecurityPolicy與安全認(rèn)證 (二)
15. AFNetworking源碼探究(十五) —— 請求序列化之架構(gòu)分析(一)
16. AFNetworking源碼探究(十六) —— 請求序列化之協(xié)議方法的實現(xiàn)(二)
17. AFNetworking源碼探究(十七) —— _AFURLSessionTaskSwizzling實現(xiàn)方法交換(轉(zhuǎn)載)(一)
18. AFNetworking源碼探究(十八) —— UIKit相關(guān)之AFNetworkActivityIndicatorManager(一)
回顧
上一篇主要講述了AFNetworkActivityIndicatorManager
數(shù)據(jù)加載指示器。這一篇主要講述了UIKit的幾個分類嗤军。
UIActivityIndicatorView+AFNetworking
1. 接口調(diào)用
這個是指示器的一個分類,看一下.h接口晃危。
@interface UIActivityIndicatorView (AFNetworking)
///----------------------------------
/// @name Animating for Session Tasks
///----------------------------------
/**
Binds the animating state to the state of the specified task.
@param task The task. If `nil`, automatic updating from any previously specified operation will be disabled.
*/
- (void)setAnimatingWithStateOfTask:(nullable NSURLSessionTask *)task;
@end
將動畫狀態(tài)綁定到指定任務(wù)的狀態(tài)叙赚。這里的參數(shù)Task,如果為nil
僚饭,則從先前指定的操作的自動更新將被禁用震叮。
這里只有上面一個暴露出來的方法。
下面我們在看下.m里面的實現(xiàn)鳍鸵,這里多了一個類AFActivityIndicatorViewNotificationObserver
苇瓣,實現(xiàn)過程如下:
#import "UIActivityIndicatorView+AFNetworking.h"
#import <objc/runtime.h>
#if TARGET_OS_IOS || TARGET_OS_TV
#import "AFURLSessionManager.h"
@interface AFActivityIndicatorViewNotificationObserver : NSObject
@property (readonly, nonatomic, weak) UIActivityIndicatorView *activityIndicatorView;
- (instancetype)initWithActivityIndicatorView:(UIActivityIndicatorView *)activityIndicatorView;
- (void)setAnimatingWithStateOfTask:(NSURLSessionTask *)task;
@end
@implementation UIActivityIndicatorView (AFNetworking)
- (AFActivityIndicatorViewNotificationObserver *)af_notificationObserver {
AFActivityIndicatorViewNotificationObserver *notificationObserver = objc_getAssociatedObject(self, @selector(af_notificationObserver));
if (notificationObserver == nil) {
notificationObserver = [[AFActivityIndicatorViewNotificationObserver alloc] initWithActivityIndicatorView:self];
objc_setAssociatedObject(self, @selector(af_notificationObserver), notificationObserver, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
return notificationObserver;
}
- (void)setAnimatingWithStateOfTask:(NSURLSessionTask *)task {
[[self af_notificationObserver] setAnimatingWithStateOfTask:task];
}
@end
@implementation AFActivityIndicatorViewNotificationObserver
- (instancetype)initWithActivityIndicatorView:(UIActivityIndicatorView *)activityIndicatorView
{
self = [super init];
if (self) {
_activityIndicatorView = activityIndicatorView;
}
return self;
}
- (void)setAnimatingWithStateOfTask:(NSURLSessionTask *)task {
NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
[notificationCenter removeObserver:self name:AFNetworkingTaskDidResumeNotification object:nil];
[notificationCenter removeObserver:self name:AFNetworkingTaskDidSuspendNotification object:nil];
[notificationCenter removeObserver:self name:AFNetworkingTaskDidCompleteNotification object:nil];
if (task) {
if (task.state != NSURLSessionTaskStateCompleted) {
UIActivityIndicatorView *activityIndicatorView = self.activityIndicatorView;
if (task.state == NSURLSessionTaskStateRunning) {
[activityIndicatorView startAnimating];
} else {
[activityIndicatorView stopAnimating];
}
[notificationCenter addObserver:self selector:@selector(af_startAnimating) name:AFNetworkingTaskDidResumeNotification object:task];
[notificationCenter addObserver:self selector:@selector(af_stopAnimating) name:AFNetworkingTaskDidCompleteNotification object:task];
[notificationCenter addObserver:self selector:@selector(af_stopAnimating) name:AFNetworkingTaskDidSuspendNotification object:task];
}
}
}
#pragma mark -
- (void)af_startAnimating {
dispatch_async(dispatch_get_main_queue(), ^{
[self.activityIndicatorView startAnimating];
});
}
- (void)af_stopAnimating {
dispatch_async(dispatch_get_main_queue(), ^{
[self.activityIndicatorView stopAnimating];
});
}
#pragma mark -
- (void)dealloc {
NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
[notificationCenter removeObserver:self name:AFNetworkingTaskDidCompleteNotification object:nil];
[notificationCenter removeObserver:self name:AFNetworkingTaskDidResumeNotification object:nil];
[notificationCenter removeObserver:self name:AFNetworkingTaskDidSuspendNotification object:nil];
}
@end
#endif
2. 接口方法的轉(zhuǎn)發(fā)實現(xiàn)
接下里我們就從那個暴露出來的方法,來看這個分類的實現(xiàn)偿乖。
// AFActivityIndicatorViewNotificationObserver實例化击罪,
// 并利用runtime綁定key對應(yīng)的value
- (AFActivityIndicatorViewNotificationObserver *)af_notificationObserver {
AFActivityIndicatorViewNotificationObserver *notificationObserver = objc_getAssociatedObject(self, @selector(af_notificationObserver));
if (notificationObserver == nil) {
notificationObserver = [[AFActivityIndicatorViewNotificationObserver alloc] initWithActivityIndicatorView:self];
// 四個參數(shù) object/key/value/policy
objc_setAssociatedObject(self, @selector(af_notificationObserver), notificationObserver, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
return notificationObserver;
}
- (void)setAnimatingWithStateOfTask:(NSURLSessionTask *)task {
// 調(diào)用了af_notificationObserver方法獲取AFActivityIndicatorViewNotificationObserver的對象。
[[self af_notificationObserver] setAnimatingWithStateOfTask:task];
}
這段代碼主要做了下面幾個工作:
- 獲取了
AFActivityIndicatorViewNotificationObserver
對象贪薪,并利用runtime綁定了key-value媳禁。 -
AFActivityIndicatorViewNotificationObserver
對象的初始化。 - 將接口那個方法轉(zhuǎn)發(fā)到
AFActivityIndicatorViewNotificationObserver
中的方法了画切。
(a) AFActivityIndicatorViewNotificationObserver對象初始化
我們先看一下初始化
@property (readonly, nonatomic, weak) UIActivityIndicatorView *activityIndicatorView;
- (instancetype)initWithActivityIndicatorView:(UIActivityIndicatorView *)activityIndicatorView
{
self = [super init];
if (self) {
// 只是簡單的賦值
_activityIndicatorView = activityIndicatorView;
}
return self;
}
這個初始化方法沒什么特別的處理就是簡單的賦值竣稽。
(b) 接口方法的轉(zhuǎn)發(fā)
該分類的調(diào)用接口會轉(zhuǎn)發(fā)到對象AFActivityIndicatorViewNotificationObserver
中去實現(xiàn)。下面看一下是如何實現(xiàn)的霍弹。
- (void)setAnimatingWithStateOfTask:(NSURLSessionTask *)task {
NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
// 先移除對上個任務(wù)的通知監(jiān)聽
[notificationCenter removeObserver:self name:AFNetworkingTaskDidResumeNotification object:nil];
[notificationCenter removeObserver:self name:AFNetworkingTaskDidSuspendNotification object:nil];
[notificationCenter removeObserver:self name:AFNetworkingTaskDidCompleteNotification object:nil];
if (task) {
// 如果任務(wù)狀態(tài)沒有完成
if (task.state != NSURLSessionTaskStateCompleted) {
UIActivityIndicatorView *activityIndicatorView = self.activityIndicatorView;
// 如果任務(wù)正在進(jìn)行毫别,就開始動畫,否則就停止動畫
if (task.state == NSURLSessionTaskStateRunning) {
[activityIndicatorView startAnimating];
} else {
[activityIndicatorView stopAnimating];
}
// 添加任務(wù)的開始暫停完成的通知
[notificationCenter addObserver:self selector:@selector(af_startAnimating) name:AFNetworkingTaskDidResumeNotification object:task];
[notificationCenter addObserver:self selector:@selector(af_stopAnimating) name:AFNetworkingTaskDidCompleteNotification object:task];
[notificationCenter addObserver:self selector:@selector(af_stopAnimating) name:AFNetworkingTaskDidSuspendNotification object:task];
}
}
}
下面看一下這個方法的實現(xiàn)典格。
首先移除對任務(wù)狀態(tài)的監(jiān)聽岛宦,防止監(jiān)聽錯誤的任務(wù)到處出錯。
首先看一下任務(wù)的狀態(tài)
NSURLSessionTaskState
耍缴,是一個枚舉值恋博,這個是蘋果的API。
typedef NS_ENUM(NSInteger, NSURLSessionTaskState) {
NSURLSessionTaskStateRunning = 0, /* The task is currently being serviced by the session */
NSURLSessionTaskStateSuspended = 1,
NSURLSessionTaskStateCanceling = 2, /* The task has been told to cancel. The session will receive a URLSession:task:didCompleteWithError: message. */
NSURLSessionTaskStateCompleted = 3, /* The task has completed and the session will receive no more delegate notifications */
} NS_ENUM_AVAILABLE(NSURLSESSION_AVAILABLE, 7_0);
如果任務(wù)沒有完成私恬,如果任務(wù)是在進(jìn)行中债沮,就開始動畫,否則就停止動畫本鸣。
- 增加對任務(wù)開始疫衩、暫停和完成的通知監(jiān)聽。在通知方法的實現(xiàn)上就是在主線程進(jìn)行開始或者停止動畫荣德。
- (void)af_startAnimating {
dispatch_async(dispatch_get_main_queue(), ^{
[self.activityIndicatorView startAnimating];
});
}
- (void)af_stopAnimating {
dispatch_async(dispatch_get_main_queue(), ^{
[self.activityIndicatorView stopAnimating];
});
}
最后在dealloc
中移除對通知的監(jiān)聽闷煤。
后記
本篇主要是UIActivityIndicatorView的分類的一些動畫的實現(xiàn)童芹,將動畫與任務(wù)的進(jìn)度進(jìn)行綁定。