共計 10155 個字符,預計需要花費 26 分鐘才能閱讀完成。
今天給大家介紹一下如何解析 AFNetworking 框架的解讀。文章的內容丸趣 TV 小編覺得不錯,現在給大家分享一下,覺得有需要的朋友可以了解一下,希望對大家有所幫助,下面跟著丸趣 TV 小編的思路一起來閱讀吧。
做 ios 開發,AFNetworking 這個網絡框架肯定都非常熟悉,也許我們平時只使用了它的部分功能,而且我們對它的實現原理并不是很清楚,就好像總是有一團迷霧在眼前一樣。
接下來我們就非常詳細的來讀一讀這個框架的代碼,我們的目標就是理解了它的思想之后,能夠明白我們的請求是如何實現的,我們的代碼哪里還需要進行改進,如果能夠更進一步,我們能夠總結出一套適合大部分應用的網絡架構思想。
能夠讓一些人從中受益。
我們先來看看整個框架的文件系統,我們先不對每個文件的作用進行說明,在整個源碼解讀最后的一篇中我們會對整個框架進行總結。會有一張清晰的圖表來說明這個問題。
我們在看一個框架的時候呢,可以這樣先看,先看每個文件的頭文件,也就是.h 文件
可以看到,有的頭文件是包含了別的頭文件的,在不考慮系統的頭文件的情況下,我們能夠發現一些比較獨立的類,從上圖中,我們可以看出
比較獨立的類有:
1.AFURLResponseSerialization.h
2.AFNetworkReachabilityManager.h
3.AFURLRequestSerialization.h
4.AFSecurityPolicy.h
下面就介紹 AFNetworkReachabilityManager.h 的內容,這個是用來監控網絡環境變化的類。
#import SystemConfiguration/SystemConfiguration.h
通過導入了這個頭文件,我們得知:網絡監控的實現是依賴 SystemConfiguration 這個 api 的。說明這個 api 能夠提供這樣的功能,至少讓我們明白了我們平時都會導入它的一個用途。
這是一個枚舉封裝,還是遵循一個使用枚舉的原則,當滿足一個有限的并具有統一主題的集合的時候,我們就考慮枚舉。在這里作者是枚舉了 4 種類型。這幾種類型能夠滿足我們開發中大部分的功能,如果不滿足,可以自行進行擴展。
NS_ASSUME_NONNULL_BEGIN
NS_ASSUME_NONNULL_END
這個是為了 swift 的可選類型配添加的,在這兩個終點的內容的參數默認都是 nonnull 的。
這段文字是對這個類的說明。我們估且不去管它說了什么,在看看蘋果官方的
這樣的內容會出現在一個屬性或者方法的上方,目的是對其內容的解釋。我看到這里就想到了我們平時的開發,我們能夠把每段代碼都當成是 api 的開發,也把注
釋寫的詳細一點。曾經看過兩種不同的說辭,一種是說把代碼注釋盡量少些,要求代碼簡介可讀性強。另一種是說注釋要詳細,著重考慮他人讀代碼的感受。個人感
覺還是寫詳細一點比較好,因為可能過一段時間之后,自己再去看自己當時寫的代碼可能就不記得了。很有可能在寫這些繁瑣的注釋的過程中,能夠想到些什么,比
如如何合并掉一些沒必要的方法等等。
本類提供了四個只讀的屬性來讓我們獲取我們需要的內容
1. 網絡狀態
2. 是否是可達的
3. 當前連接是否是 WWAN
4. 當前連接是夠是 WiFi
四個屬性均為只讀屬性,只給了用戶訪問權,注意 BOOL 屬性一般是要寫 getter 方法的。
作者使用了這個來分隔同一類中不同功能模塊。這個算是個人習慣問題吧。舉個平時開發的例子,在.m 文件中我個人使用 #pragma mark 分隔不同功能。
提供了 5 中初始化方法,能夠滿足大部分的需求。
SCNetworkReachabilityRef 這個很重要,這個類的就是基于它開發的。
+ (instancetype)managerForDomain:(NSString *)domain; 監聽制定 domain 的網絡狀態。
+ (instancetype)managerForAddress:(const void *)address; 監聽某個 socket 地址的網絡狀態,socket 通信請看這篇文章:socket 通信
打開和關閉監聽的方法。
返回一個網絡狀態的本地語言的字符串。往往我們可以根據這個字符串來告訴用戶,當前網絡發生了什么,當然,也可以根據狀態自定義提示文字。
設置網絡轉態改變的回調,監聽網絡改變的回調有兩種方式:
1. 使用上邊的這個方法。
2. 監聽 AFNetworkingReachabilityDidChangeNotification 通知。
這個是與網絡狀態變化相關的通知。接受的通知中會有一個 userinfo 是一個 NSDictionary 其中 key 就是
AFNetworkingReachabilityNotificationStatusItem
這簡單的兩行代碼能夠告訴我們的是,我們平時的開發中 但凡設計到發通知的功能,我們應該把通知的字符串封裝到一個專有的文件中,同時在文件內部按不同模塊進行區分,當然必要的注釋也很有必要。
ps: FOUNDATION_EXPORT 和 #define 都能定義常量。FOUNDATION_EXPORT 能夠使用 == 進行判斷,效率略高。而且能夠隱藏定義細節 (就是實現部分不在. 中)
對函數:根據狀態獲取字符串 聲明。
好了,這個類的.h 文件我們已經非常相信的進行解讀了,我們并不是大概的說了下他提供的功能,而是通過讀每行代碼,我們能聯想到什么,什么東西能幫助我們更好的編程。
我們接著看 AFNetworkReachabilityManager.m 的內容
這幾個頭文件是系統庫,是為了后邊的 sockaddr_in6 / sockaddr_in 準備的,不熟悉的可以看這篇文章 socket 通信
這幾個就沒什么好說的了,我們接著看
這個方法是對.h 中最后一個方法的實現。指的我們注意的是 NSLocalizedStringFromTable 這個宏。為什么要注意它呢?
這就涉及到本地國際化的問題。所謂的國際化就是讓你的 app 能夠根據不同的語言顯示相對應的語言。
*** 但這并不簡單,沒有經驗的開發人員,一開始可能不會做這樣的設置,如果日后需要國際話了,在做就很麻煩了。所以說在開中,但凡使用到字符串的地方都要考慮語言的不同。不同的語言下,一個意思的表達所使用的字符串長度是不一樣的,這就影射出空間的寬度可能會不一樣。
好了,國際化的內容就不說了,請自行搜索。
1 /** 2 * 根據 SCNetworkReachabilityFlags 這個網絡標記來轉換成我們在開發中經常使用的網絡狀態 3 1. 不能連接網絡 4 2. 蜂窩連接 5 3.WiFi 連接 6 4. 未知連接 7 */ 8 static AFNetworkReachabilityStatus AFNetworkReachabilityStatusForFlags(SCNetworkReachabilityFlags flags) { 9 10 // 是否能夠到達 11 BOOL isReachable = ((flags kSCNetworkReachabilityFlagsReachable) != 0);12 13 // 在聯網之前需要建立連接 14 BOOL needsConnection = ((flags kSCNetworkReachabilityFlagsConnectionRequired) != 0);15 16 // 是否可以自動連接 17 BOOL canConnectionAutomatically = (((flags kSCNetworkReachabilityFlagsConnectionOnDemand ) != 0) || ((flags kSCNetworkReachabilityFlagsConnectionOnTraffic) != 0));18 19 // 是否可以連接,在不需要用戶手動設置的前提下 20 BOOL canConnectWithoutUserInteraction = (canConnectionAutomatically (flags kSCNetworkReachabilityFlagsInterventionRequired) == 0);21 22 // 是否可以聯網的條件 1. 能夠到達 2. 不需要建立連接或者不需要用戶手動設置連接 就表示能夠連接到網絡 23 BOOL isNetworkReachable = (isReachable (!needsConnection || canConnectWithoutUserInteraction));24 25 AFNetworkReachabilityStatus status = AFNetworkReachabilityStatusUnknown;26 if (isNetworkReachable == NO) {27 status = AFNetworkReachabilityStatusNotReachable;28 }29 #if TARGET_OS_IPHONE30 else if ((flags kSCNetworkReachabilityFlagsIsWWAN) != 0) {31 status = AFNetworkReachabilityStatusReachableViaWWAN;32 }33 #endif34 else {35 status = AFNetworkReachabilityStatusReachableViaWiFi;36 }37 38 return status;39 }
這個方法根據 SCNetworkReachabilityFlags 這個標記轉換成我們自定義的枚舉類型。至于轉換規則,上邊的代碼中注釋部分寫的很清楚。
*** 在這里不得不多說幾句,很多框架中都會把一個類中的私有方法寫成這樣。為什么呢?我們在開發中經常會寫成 - (void)funcName; 這樣的私有方法。
我個人的意見是一個類中的私有方法寫成 static void funcName() 這樣的 c 函數比較好。
1. 在文件的最前方,比較容易查找
2. 可以適當的使用內聯函數,提高效率。
根據一個標識 來處理 Block 和通知。保證兩者同一狀態。
包含了 類中需要處理的屬性。
來看這個最基本的初始化方法,初始化了自身的屬性。
CFRetain() 后要記得 CFRelease().
通過一個 socket 地址來初始化。首先新建 SCNetworkReachabilityRef 對象,然后調用 initWithReachability: 方法。記得手動管理內存。
這個方法基本同上。
綜合上邊兩個方法,我們發現 SCNetworkReachabilityRef 有兩個創建方法:
1. SCNetworkReachabilityCreateWithName
2. SCNetworkReachabilityCreateWithAddress
由于 IPv6 是 ios9 和 os_x 10.11 后邊推出的,所有要進行版本判斷。這禮拜呢設計到的 socket 的知識,請看 socket 通信
通過這段代碼我們能學到什么呢?
1,方法的創建也是有順序的,可以使用函數訪問函數的思想。
2. @if 這樣的預編譯指令能夠替換掉代碼中部分 if else。好處就是代碼會不會被編譯的區別。
單例的寫法。
對需要釋放時,做一些處理。
這個是.h 文件暴露出來的 3 個 BOOL 屬性的 getter 方法,注意,由于我們在 @property 中定義了 getter 方法,所以 getter 方法就要寫成我們定義的那種。
從這 3 個方法中也能看出,函數嵌套的思想還是很重要,要想做到這一點,只能是多想才行。
這個算是這個類的核心方法,設置監聽網咯監聽。
我們先來了解下基礎知識。
SCNetworkReachabilityContext
點進去,會發現這是一個結構體,一般 c 語言的結構體是對要保存的數據的一種描述
1. 第一個參數接受一個 signed long 的參數
2. 第二個參數接受一個 void * 類型的值,相當于 oc 的 id 類型,void * 可以指向任何類型的參數
3. 第三個參數 是一個函數 目的是對 info 做 retain 操作,
4. 第四個參數是一個函數,目的是對 info 做 release 操作
5. 第五個參數是 一個函數,根據 info 獲取 Description 字符串
在這里我們要攜帶的這個 info 就是下邊的這個 block
1 __weak __typeof(self)weakSelf = self; 2 AFNetworkReachabilityStatusBlock callback = ^(AFNetworkReachabilityStatus status) { 3 __strong __typeof(weakSelf)strongSelf = weakSelf; 4 5 strongSelf.networkReachabilityStatus = status; 6 if (strongSelf.networkReachabilityStatusBlock) { 7 strongSelf.networkReachabilityStatusBlock(status); 8 } 9 10 };
retain 和 release 函數是下邊的這兩個函數
1 static const void * AFNetworkReachabilityRetainCallback(const void *info) {2 return Block_copy(info);3 }4 5 static void AFNetworkReachabilityReleaseCallback(const void *info) {6 if (info) {7 Block_release(info);8 }9 }
設置網絡監控分為下邊幾個步驟:
1. 我們先新建上下文
1 SCNetworkReachabilityContext context = {0, (__bridge void *)callback, AFNetworkReachabilityRetainCallback, AFNetworkReachabilityReleaseCallback, NULL};
2. 設置回調
1 SCNetworkReachabilitySetCallback(self.networkReachability, AFNetworkReachabilityCallback, context);
其中這個 AFNetworkReachabilityCallback 是這樣被定義的一個函數
typedef void (*SCNetworkReachabilityCallBack) (
SCNetworkReachabilityRef target,
SCNetworkReachabilityFlags flags, void * __nullable info
);
在本類中
1 static void AFNetworkReachabilityCallback(SCNetworkReachabilityRef __unused target, SCNetworkReachabilityFlags flags, void *info) {2 AFPostReachabilityStatusChange(flags, (__bridge AFNetworkReachabilityStatusBlock)info);3 }
3. 加入 RunLoop 池
1 SCNetworkReachabilityScheduleWithRunLoop(self.networkReachability, CFRunLoopGetMain(), kCFRunLoopCommonModes);
其中 CFRunLoopGetMain() 代表主 RunLoop
ok,差不多已經完成
在異步線程 發送一次當前的網絡狀態。
停止網絡監控
這兩個方法沒什么好說的了,一個是 getter 一個是 setter
注冊鍵值依賴,這個可能大家平時用的比較少。可以了解一下
比如說一個類 User 中有兩個屬性
還有一個卡片的類 card
我們寫一個 info 的 setter 和 getter 方法,
1 @interface User :NSObject 2 @property (nonatomic,copy)NSString *name; 3 @property (nonatomic,assign)NSUInteger age; 4 @end 5 6 7 8 @interface card :NSObject 9 @property (nonatomic,copy)NSString *info;10 @property (nonatomic,strong)User *user;11 @end12 @implementation card13 14 - (NSString *)info {15 return [NSString stringWithFormat:@ %@/%lu ,_user.name,(unsigned long)_user.age];16 }17 - (void)setInfo:(NSString *)info {18 19 NSArray *array = [info componentsSeparatedByString:@ / 20 _user.name = array[0];21 _user.age = [array[1] integerValue];22 23 }24 25 + (NSSet NSString * *)keyPathsForValuesAffectingValueForKey:(NSString *)key {26 NSSet * keyPaths = [super keyPathsForValuesAffectingValueForKey:key];27 NSArray * moreKeyPaths = nil;28 29 if ([key isEqualToString:@ info])30 {31 moreKeyPaths = [NSArray arrayWithObjects:@ user.name , @ user.age , nil];32 }33 34 if (moreKeyPaths)35 {36 keyPaths = [keyPaths setByAddingObjectsFromArray:moreKeyPaths];37 }38 39 return keyPaths;40 }41 42 @end
gh.dokee.cn/article/content-2292769-34004.html
gh.dokee.cn/article/content-2292768-34004.html
gh.dokee.cn/article/content-2292766-34004.html
gh.dokee.cn/article/content-2292765-34004.html
gh.dokee.cn/article/content-2292764-34004.html
gh.dokee.cn/article/content-2292763-34004.html
gh.dokee.cn/article/content-2292762-34004.html
gh.dokee.cn/article/content-2292761-34004.html
gh.dokee.cn/article/content-2292760-34004.html
gh.dokee.cn/article/content-2292759-34004.html
gh.dokee.cn/article/content-2292758-34004.html
bbs.open.qq.com/thread-15334805-1-1.html
bbs.open.qq.com/thread-15335348-1-1.html
bbs.open.qq.com/thread-15335576-1-1.html
bbs.open.qq.com/thread-15335715-1-1.html
http://bbs.open.qq.com/thread-15335916-1-1.html
http://bbs.open.qq.com/thread-15335876-1-1.html
http://bbs.open.qq.com/thread-15336398-1-1.html
http://bbs.open.qq.com/thread-15336484-1-1.html
http://bbs.open.qq.com/thread-15336547-1-1.html
http://bbs.open.qq.com/thread-15336614-1-1.html
http://bbs.open.qq.com/thread-15336697-1-1.html
http://bbs.open.qq.com/thread-15336806-1-1.html
http://bbs.open.qq.com/thread-15340763-1-1.html
www.baiyewang.com/s4209086.html
http://bl.gamebbs.qq.com/forum.php?mod=viewthread tid=11675819
http://bbs.open.qq.com/thread-15343974-1-1.html
http://bbs.open.qq.com/thread-15344107-1-1.html
http://caimi68.lofter.com/post/1e3e0a7a_bbb5392
http://caimi68.lofter.com/post/1e3e0a7a_bbb539f
http://caimi68.lofter.com/post/1e3e0a7a_bbb539e
http://caimi68.lofter.com/post/1e3e0a7a_bbb539d
http://caimi68.lofter.com/post/1e3e0a7a_bbb539c
http://caimi68.lofter.com/post/1e3e0a7a_bbb53a0
http://caimi68.lofter.com/post/1e3e0a7a_bbb53a1
http://caimi68.lofter.com/post/1e3e0a7a_bbb53a2
http://caimi68.lofter.com/post/1e3e0a7a_bbb53a4
http://bbs.open.qq.com/thread-15345770-1-1.html
http://bbs.open.qq.com/thread-15345813-1-1.html
http://bbs.open.qq.com/thread-15345854-1-1.html
http://bbs.open.qq.com/thread-15345888-1-1.html
http://bbs.open.qq.com/thread-15345937-1-1.html
http://bbs.open.qq.com/thread-15346013-1-1.html
http://bbs.open.qq.com/thread-15346046-1-1.html
http://bbs.open.qq.com/thread-15346098-1-1.html
http://bbs.open.qq.com/thread-15346138-1-1.html
http://bbs.open.qq.com/thread-15346194-1-1.html
http://bbs.open.qq.com/thread-15346240-1-1.html
http://bbs.open.qq.com/thread-15346345-1-1.html
http://g.jandan.net/s/6319
http://g.jandan.net/s/6320
http://g.jandan.net/s/6321
http://g.jandan.net/s/6322
http://g.jandan.net/s/6323
以上就是如何解析 AFNetworking 框架的解讀的全部內容了,更多與如何解析 AFNetworking 框架的解讀相關的內容可以搜索丸趣 TV 之前的文章或者瀏覽下面的文章進行學習哈!相信丸趣 TV 小編會給大家增添更多知識, 希望大家能夠支持一下丸趣 TV!