原文链接 : http://blog.csdn.net/sinat_30162391/article/details/53321046

前言: 这个系列可能不会分析, Masonry如何如何好, 估计多在分析源码写法, 不清楚的语法, 用了什么知识点, 可能是这样, 写成什么样也不确定, Masonry 是一个关于iOS开发的布局框架, Masonry是对NSLayoutConstraint 的封装, 你知道的NSLayoutConstraint这个家伙使用起来很麻烦的, 语法相当的啰嗦. 所以Masonry 简化了这个家伙的使用方式, 同时Masonry有一个小兄弟, 也在成长中, 成长的也是不错, 你可以在Masonry的家里找到这个家伙(SnapKit), 不同的是SnapKit 是使用Siwft 写的, 如果你都知道, 就当是我在凑字数(来 qq群打我好啦 认真脸), 今天就主要介绍一些Masonry 相关的干货, 反正你知道我是学习记录, 谈不上分享的, 我一贯就是这个态度的[囧].
下面的这张图, 简单介绍了Masonry的主要大部分类, 你说: 没写全? 对的. 我能说没有地方画让我删了吗? 认真.

可能会写这样几篇
厚积薄发之从Masonry 源码探Objective-C [开篇]
[厚积薄发之从Masonry 源码探Objective-C [开篇 续]]
[厚积薄发之从Masonry 源码探Objective-C [开篇 续续]
[厚积薄发之从Masonry 源码探Objective-C [开篇 续续续]
[厚积薄发之从Masonry 源码探Objective-C [终篇 - 有始有终 希望最后能够完美]

目录

  • Objective-C可变参数
  • 内联函数 inline
  • mas_equalTo这个宏的实现

可变参数: 在开始之前, 我决定先看看这个小知识, 当然你了解C 语言对此并不陌生, 然而我不像你, 我已经把以前学的知识, 交还给我的teacher了. 你可能也忘记了来跟我一起复习一遍, 在C 语言中的解释大致是这个样子的, 可变参数的实现必然不能缺少VA_LIST,
VA_LIST 是在C语言中是这样解释的, 用来解决变参问题的一组宏,所在头文件:#include <stdarg.h>,用于获取不确定个数的参数
而在Objective-C中 同样也有关于处理不确定参数个数的实现使用va_list相关, 接下来通过一段简单的代码进行演示.

可变参数在OC中如何实现?

  • va_list定义一个va_list变量, 这个变量的是指向参数的指针
  • va_start使用宏 定义va_list变量
  • va_argva_arg返回可变的参数,va_arg的第二个参数是你要返回的参数的类型,如果函数有多个可变参数的,依次调用va_arg获取各个参数
  • va_end用va_end宏结束可变参数的获取
- (NSMutableArray *)vaListUsing:(NSString *)p1,...NS_REQUIRES_NIL_TERMINATION{NSMutableArray *array = [NSMutableArray array];// 第一个参数进数组[array addObject:p1];// 定义一个va_list变量, 这个变量的是指向参数的指针va_list v;id vStr;// 使用宏定义va_list变量va_start(v, p1);// va_arg返回可变的参数,va_arg的第二个参数是你要返回的参数的类型,如果函数有多个可变参数的,依次调用va_arg获取各个参数while ((vStr = va_arg(v, id))) {[array addObject:vStr];}// 用va_end宏结束可变参数的获取va_end(v);return array;
}
NSMutableArray *array = [self vaListUsing:@"Cancel", @"Other",@"OK", nil];
NSLog(@"%@", array); 

这是获取的打印结果, 以上就是我通过代码的形式表现出来的, 你可以通过获取的参数名, 参数个数, 可进行适当的UI布局什么的.
2016-11-23 15:58:09.225 Masonry*阅读理解**[5338:1112595] (
* Cancel,*
* Other,*
* OK*
)

以上是不是跑题了, 我的回答是 并没有! 你也相信我不能在这瞎扯淡.
接下来看看Masonry中如何使用这个小知识的呢.

在MASUtilities中

先看下面这段源码, 通过上面的介绍, 我觉的你可能有点能明白了, 稍后解释代码, 首先看看inline C和C++语言中inline用来声明内联函数的, 我还是有些印象的 作用是是 用来替代C中表达式形式的宏定义的. 而在OC用也是有同样的作用.

static inline id _MASBoxValue(const char *type, ...) {va_list v;va_start(v, type);id obj = nil;if (strcmp(type, @encode(id)) == 0) {id actual = va_arg(v, id);obj = actual;} else if (strcmp(type, @encode(CGPoint)) == 0) {CGPoint actual = (CGPoint)va_arg(v, CGPoint);obj = [NSValue value:&actual withObjCType:type];} else if (strcmp(type, @encode(CGSize)) == 0) {CGSize actual = (CGSize)va_arg(v, CGSize);obj = [NSValue value:&actual withObjCType:type];} else if (strcmp(type, @encode(MASEdgeInsets)) == 0) {MASEdgeInsets actual = (MASEdgeInsets)va_arg(v, MASEdgeInsets);obj = [NSValue value:&actual withObjCType:type];} else if (strcmp(type, @encode(double)) == 0) {double actual = (double)va_arg(v, double);obj = [NSNumber numberWithDouble:actual];} else if (strcmp(type, @encode(float)) == 0) {float actual = (float)va_arg(v, double);obj = [NSNumber numberWithFloat:actual];} else if (strcmp(type, @encode(int)) == 0) {int actual = (int)va_arg(v, int);obj = [NSNumber numberWithInt:actual];} else if (strcmp(type, @encode(long)) == 0) {long actual = (long)va_arg(v, long);obj = [NSNumber numberWithLong:actual];} else if (strcmp(type, @encode(long long)) == 0) {long long actual = (long long)va_arg(v, long long);obj = [NSNumber numberWithLongLong:actual];} else if (strcmp(type, @encode(short)) == 0) {short actual = (short)va_arg(v, int);obj = [NSNumber numberWithShort:actual];} else if (strcmp(type, @encode(char)) == 0) {char actual = (char)va_arg(v, int);obj = [NSNumber numberWithChar:actual];} else if (strcmp(type, @encode(bool)) == 0) {bool actual = (bool)va_arg(v, int);obj = [NSNumber numberWithBool:actual];} else if (strcmp(type, @encode(unsigned char)) == 0) {unsigned char actual = (unsigned char)va_arg(v, unsigned int);obj = [NSNumber numberWithUnsignedChar:actual];} else if (strcmp(type, @encode(unsigned int)) == 0) {unsigned int actual = (unsigned int)va_arg(v, unsigned int);obj = [NSNumber numberWithUnsignedInt:actual];} else if (strcmp(type, @encode(unsigned long)) == 0) {unsigned long actual = (unsigned long)va_arg(v, unsigned long);obj = [NSNumber numberWithUnsignedLong:actual];} else if (strcmp(type, @encode(unsigned long long)) == 0) {unsigned long long actual = (unsigned long long)va_arg(v, unsigned long long);obj = [NSNumber numberWithUnsignedLongLong:actual];} else if (strcmp(type, @encode(unsigned short)) == 0) {unsigned short actual = (unsigned short)va_arg(v, unsigned int);obj = [NSNumber numberWithUnsignedShort:actual];}va_end(v);return obj;
}#define MASBoxValue(value) _MASBoxValue(@encode(__typeof__((value))), (value))

由源代码引申之内联函数

定义: 内联函数是指用inline关键字修饰的函数
作用: 去掉函数调用带来的开销
这个说的可以 可以去看看
代码示例
仿照Masonry的示例代码, 我简单测试了一下, 准确性有待考察, 不过粗略的看, 貌似内联函数效率高一点, 你怎么看? 欢迎评论拍砖. 教我做人.

static inline

static inline int xtAdd(int x, int y){int res = x + y;return res;
}
#define RESXyAdd(x, y) xtAdd(x, y)
    NSDate *tmpStartData = [NSDate date];int res = RESXyAdd(2, 3);// 内联// 2016-11-24 14:06:13.816 Masonry解析[7209:1504811] >>>>>>>>>>cost time = 0.608981 ms// 2016-11-24 14:00:57.229 Masonry解析[6870:1496409] >>>>>>>>>>cost time = 0.648022 ms// 2016-11-24 14:01:38.670 Masonry解析[6898:1497238] >>>>>>>>>>cost time = 0.645995 ms// 非内联// 2016-11-24 14:03:57.975 Masonry解析[7052:1500940] >>>>>>>>>>cost time = 0.657976 ms// 2016-11-24 14:04:57.955 Masonry解析[7101:1502351] >>>>>>>>>>cost time = 0.651002 msNSLog(@"res === %d", res);double deltaTime = [[NSDate date] timeIntervalSinceDate:tmpStartData];NSLog(@">>>>>>>>>>cost time = %f ms", deltaTime * 1000);

接下来通过Masonry的使用来解释上面提到的代码
首先我定义了一个View 距上左88 宽高88 我分别可以使用make.width.height.mas_equalTo(88); make.width.height.mas_equalTo(@88);
或者 make.width.height.mas_equalTo(@88) 通过这个宏我分别可以实现相应很多操作. 其实这些都是通过上面提到的内联函数实现的. 先通过strcmp这个库函数比较传进来的类型跟什么类型匹配, 之后放回相应的对象. 完成对象的校验. 这样的效率很高, 同时使用方便.

    UIView *view = [UIView new];[self.view addSubview:view];view.backgroundColor = [UIColor redColor];[view mas_makeConstraints:^(MASConstraintMaker *make) {//make.top.equalTo(self.view.mas_top).with.offset(88);make.left.equalTo(self.view.mas_left).with.offset(88);// 我通过这个宏 传递88给width 和 heightmake.width.height.mas_equalTo(88);// 或者 @88 // make.width.height.mas_equalTo(@88);// 最终都是通过上述的内联函数实现了相应的类型对应// make.size.mas_equalTo(CGSizeMake(88, 88));}];

#define mas_equalTo(…) equalTo(MASBoxValue((VA_ARGS)))
mas_equalTo是个上面这样表示的宏定义
#define MASBoxValue(value) _MASBoxValue(@encode(typeof((value))), (value))
而 MASBoxValue 最终是上面这个宏定义, 而最终 _MASBoxValue就是最上面提到的一大坨代码(那个内联函数). 而不确定参数, 我通过文章的开头, 也进行了交代.

总结: 这个MASUtilities 文件 , 剩下就是一些重命名, 和宏定义的一些东西了, 这篇就到这, 篇幅太长是没有耐心看下去的, 起个抛砖引玉的作用, 先这样, 下一篇 还不知道怎么写, 尽力写的全面一点, 让自己有所收获.

欢迎来我的交流群交流498143780
或者关注我的公共号xt1005430006 或者加我的微信 1005430006

从Masonry 源码探 Objective-C [源码学习开篇]相关推荐

  1. matplotlib工具栏源码探析四(自定义工具项图标)

    在matplotlib工具栏源码探析二(添加.删除内置工具项)和matplotlib工具栏源码探析三(添加.删除自定义工具项)两篇文章中,仔细观察会发现,不论内置工具项还是自定义工具项都没有图标,但是 ...

  2. SpringCloud源码探析(三)-Nacos集群搭建与配置管理

    1.概述 上一篇文章SpringCloud源码探析(二)-Nacos注册中心分析了nacos单机版的部署以及SpringBoot整合nacos,nacos不仅仅可以作为注册中心,也可以作为配置中心.本 ...

  3. Selenium3 Python WebDriver API源码探析(19)加载FireFox用户配置文件

    FireFox用户配置文件 Firefox 将用户个人信息(例如书签.密码.首选项.扩展.Cookie.证书等)保存在一系列文件中,它们被叫做用户配置文件,它们与 Firefox 的程序文件保存在不同 ...

  4. UVM config_db机制源码探微

    文章目录 1. uvm_config_db 基础 1.1. 简单set 1.2. 多重set 2. uvm_resource 2.1. uvm_resource_base 2.2. uvm_resou ...

  5. 直播源码和短视频源码,相亲相爱的一家人

    直播源码和短视频源码,相亲相爱的一家人 从直播的百播大战,到如今的趋于稳定:从短视频的兴起,到如今的竞争发展.直播和短视频两条线,开始相交,直播里面添加短视频功能,短视频里面也添加了直播. 在直播里面 ...

  6. 【Linux 内核 内存管理】优化内存屏障 ③ ( 编译器屏障 | 禁止 / 开启内核抢占 与 方法保护临界区 | preempt_disable 禁止内核抢占源码 | 开启内核抢占源码 )

    文章目录 一.禁止 / 开启内核抢占 与 方法保护临界区 二.编译器优化屏障 三.preempt_disable 禁止内核抢占 源码 四.preempt_enable 开启内核抢占 源码 一.禁止 / ...

  7. 【Android 插件化】Hook 插件化框架 ( 从 Hook 应用角度分析 Activity 启动流程 二 | AMS 进程相关源码 | 主进程相关源码 )

    Android 插件化系列文章目录 [Android 插件化]插件化简介 ( 组件化与插件化 ) [Android 插件化]插件化原理 ( JVM 内存数据 | 类加载流程 ) [Android 插件 ...

  8. 为什么要看源码、如何看源码,高手进阶必看

    由于项目的需求,最近花了较多的时间来看开源项目的代码,在本文中,简单总结一下对为什么要看源码.如何看源码这两个问题的思考. 看源码的意义 看源码只是一种方法.手段,而不是目的.我也曾经给自己制定过&q ...

  9. python 网站 源码_在线浏览美图源码,附带python源码

    源码介绍 本源码由@香谢枫林 开发,首页图片做了浏览器窗口自适应,最大化占满PC浏览器和移动浏览器的窗口,并且防止出现滚动条. 源码截图 美图源码1 美图源码2 功能介绍 首页图片设置了4个点击功能区 ...

最新文章

  1. MindInsight训练可视整体设计介绍
  2. 百度Apollo首次披露纯视觉L4无人车方案:10摄像头,对标Mobileye
  3. python最简单的架构_Python实现简单状态框架的方法
  4. 为什么总说做产品经理的门槛低?
  5. 资深猎头揭露:他们为何能年薪百万?
  6. colab显示没有gpu的解决方法
  7. parquet格式_【存储】基于列存之Parquet格式
  8. 2018年广西计算机一级,关于2018年上半年广西壮族自治区全国计算机等级考试报名工作的通知...
  9. C++ 类对象和 指针的区别
  10. jQuery事件相关方法
  11. Kaldi语料的两种切分/组织方式及其处理
  12. 基于Springboot+Vue.js的校园二手商城
  13. css 适配mac 字体,CSS:仅在mac上使用字体
  14. 计算机中丢失msvcr100.dll怎么办,会声会影计算机中丢失MSVCR100.dll解决方案-计算机中丢失MSVCR100.dll怎么解决_好特教程...
  15. C语言复健(数组) 珠心算测验
  16. tomcat连接超时
  17. 窗帘盒有哪些种类,怎样安装窗帘盒?
  18. 谈如何把科大建成一流大学
  19. java毕业生设计在线点餐系统计算机源码+系统+mysql+调试部署+lw
  20. TCP/IP详解卷一读书笔记一

热门文章

  1. ESP8266-Arduino编程实例-APDS-9930环境光和趋近感器驱动
  2. 使用 canvas 实现 js 取渐变色某段色值
  3. 【训练题22:线性求逆元】【模板】乘法逆元 | 洛谷 P3811
  4. 《互联网软件应用与开发(网络程序设计)》
  5. web期末作业网页设计——JavaScript
  6. UE4后期处理之水下效果
  7. 01背包一维dp数组的实现
  8. 13 PHP次末跳弹出pemultimate hop popping
  9. PMI-ACP练习题(23)
  10. Spring Boot教程(十七)属性配置文件详解(2)