从Masonry 源码探 Objective-C [源码学习开篇]
原文链接 : 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_arg
va_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 [源码学习开篇]相关推荐
- matplotlib工具栏源码探析四(自定义工具项图标)
在matplotlib工具栏源码探析二(添加.删除内置工具项)和matplotlib工具栏源码探析三(添加.删除自定义工具项)两篇文章中,仔细观察会发现,不论内置工具项还是自定义工具项都没有图标,但是 ...
- SpringCloud源码探析(三)-Nacos集群搭建与配置管理
1.概述 上一篇文章SpringCloud源码探析(二)-Nacos注册中心分析了nacos单机版的部署以及SpringBoot整合nacos,nacos不仅仅可以作为注册中心,也可以作为配置中心.本 ...
- Selenium3 Python WebDriver API源码探析(19)加载FireFox用户配置文件
FireFox用户配置文件 Firefox 将用户个人信息(例如书签.密码.首选项.扩展.Cookie.证书等)保存在一系列文件中,它们被叫做用户配置文件,它们与 Firefox 的程序文件保存在不同 ...
- 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 ...
- 直播源码和短视频源码,相亲相爱的一家人
直播源码和短视频源码,相亲相爱的一家人 从直播的百播大战,到如今的趋于稳定:从短视频的兴起,到如今的竞争发展.直播和短视频两条线,开始相交,直播里面添加短视频功能,短视频里面也添加了直播. 在直播里面 ...
- 【Linux 内核 内存管理】优化内存屏障 ③ ( 编译器屏障 | 禁止 / 开启内核抢占 与 方法保护临界区 | preempt_disable 禁止内核抢占源码 | 开启内核抢占源码 )
文章目录 一.禁止 / 开启内核抢占 与 方法保护临界区 二.编译器优化屏障 三.preempt_disable 禁止内核抢占 源码 四.preempt_enable 开启内核抢占 源码 一.禁止 / ...
- 【Android 插件化】Hook 插件化框架 ( 从 Hook 应用角度分析 Activity 启动流程 二 | AMS 进程相关源码 | 主进程相关源码 )
Android 插件化系列文章目录 [Android 插件化]插件化简介 ( 组件化与插件化 ) [Android 插件化]插件化原理 ( JVM 内存数据 | 类加载流程 ) [Android 插件 ...
- 为什么要看源码、如何看源码,高手进阶必看
由于项目的需求,最近花了较多的时间来看开源项目的代码,在本文中,简单总结一下对为什么要看源码.如何看源码这两个问题的思考. 看源码的意义 看源码只是一种方法.手段,而不是目的.我也曾经给自己制定过&q ...
- python 网站 源码_在线浏览美图源码,附带python源码
源码介绍 本源码由@香谢枫林 开发,首页图片做了浏览器窗口自适应,最大化占满PC浏览器和移动浏览器的窗口,并且防止出现滚动条. 源码截图 美图源码1 美图源码2 功能介绍 首页图片设置了4个点击功能区 ...
最新文章
- MindInsight训练可视整体设计介绍
- 百度Apollo首次披露纯视觉L4无人车方案:10摄像头,对标Mobileye
- python最简单的架构_Python实现简单状态框架的方法
- 为什么总说做产品经理的门槛低?
- 资深猎头揭露:他们为何能年薪百万?
- colab显示没有gpu的解决方法
- parquet格式_【存储】基于列存之Parquet格式
- 2018年广西计算机一级,关于2018年上半年广西壮族自治区全国计算机等级考试报名工作的通知...
- C++ 类对象和 指针的区别
- jQuery事件相关方法
- Kaldi语料的两种切分/组织方式及其处理
- 基于Springboot+Vue.js的校园二手商城
- css 适配mac 字体,CSS:仅在mac上使用字体
- 计算机中丢失msvcr100.dll怎么办,会声会影计算机中丢失MSVCR100.dll解决方案-计算机中丢失MSVCR100.dll怎么解决_好特教程...
- C语言复健(数组) 珠心算测验
- tomcat连接超时
- 窗帘盒有哪些种类,怎样安装窗帘盒?
- 谈如何把科大建成一流大学
- java毕业生设计在线点餐系统计算机源码+系统+mysql+调试部署+lw
- TCP/IP详解卷一读书笔记一