共计 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!