该文章阅读的 Masonry 的版本为 1.1.0。

这个类我们可以叫它“约束视图及其属性类”,它封装了设置约束的视图和其设置约束的属性,也就是 view1attr1,或是 view2attr2

1.公共属性

@property (nonatomic, weak, readonly) MAS_VIEW *view;
复制代码

这个属性保存的是约束所在的视图,可以为 nil。


@property (nonatomic, weak, readonly) id item;
复制代码

这个属性保存的是约束的 item,也就是 NSLayoutConstraint 中的 view1view2, 大多数情况,item 就是上面的属性 view。

当如下代码设置约束时:

make.top.equalTo(self.mas_topLayoutGuide);
复制代码

或者:

make.top.equalTo(self.view.mas_safeAreaLayoutGuideTop);
复制代码

这类相关的约束时,item 和 view 才不相同。view 还是保存约束所在的视图,但 item 就是保存 UIViewController 的 topLayoutGuide 属性或者 UIView 的 safeAreaLayoutGuide 属性了。


@property (nonatomic, assign, readonly) NSLayoutAttribute layoutAttribute;
复制代码

这个属性中保存的就是约束的属性,也就是 NSLayoutConstraint 中的 attr1attr2

2.公共方法

- (id)initWithView:(MAS_VIEW *)view layoutAttribute:(NSLayoutAttribute)layoutAttribute;
复制代码

以指定约束的视图和约束的属性初始化的方法。


- (id)initWithView:(MAS_VIEW *)view item:(id)item layoutAttribute:(NSLayoutAttribute)layoutAttribute;
复制代码

以指定约束的视图,约束的 item 和约束的属性初始化的方法。


- (BOOL)isSizeAttribute;
复制代码

这个方法用于获取设置的约束的属性是否是 size 类型的,也就是直接设置宽和高类型的。

3.方法实现

3.1 公共方法的实现

- (id)initWithView:(MAS_VIEW *)view layoutAttribute:(NSLayoutAttribute)layoutAttribute {
// 从这个方法的实现中,我们就可以看到,view 和 item 在大多数情况下是同一个对象
self = [self initWithView:view item:view layoutAttribute:layoutAttribute];
return self;
}
复制代码
- (id)initWithView:(MAS_VIEW *)view item:(id)item layoutAttribute:(NSLayoutAttribute)layoutAttribute {
// 在这个方法中只是保存了一下传递的参数
self = [super init];
if (!self) return nil; _view = view;
_item = item;
_layoutAttribute = layoutAttribute; return self;
}
复制代码
- (BOOL)isSizeAttribute {
// 只要是直接设置了约束的宽或高就返回 YES,否则就是 NO
return self.layoutAttribute == NSLayoutAttributeWidth
|| self.layoutAttribute == NSLayoutAttributeHeight;
}
复制代码

3.2 父类方法的重写

- (BOOL)isEqual:(MASViewAttribute *)viewAttribute {
// 先判断是否是当前类或其子类
if ([viewAttribute isKindOfClass:self.class]) {
// 必须满足设置约束的视图和设置约束的属性都相等,才算两个对象相等。
return self.view == viewAttribute.view
&& self.layoutAttribute == viewAttribute.layoutAttribute;
}
// 如果不是当前类或其子类,就直接调用父类方法判断。
return [super isEqual:viewAttribute];
}
复制代码
- (NSUInteger)hash {
// 这个地方就用到了我们在上一篇文章 MASUtilities 中看到的宏
// 首先将设置约束的视图的 hash 从中间反转,然后再异或上设置约束的属性
return MAS_NSUINTROTATE([self.view hash], MAS_NSUINT_BIT / 2) ^ self.layoutAttribute;
}
复制代码

为什么要重新父类的这两个方法?

  • 这就涉及到当对象被添加到 NSSet 对象中,或者对象作为 key 添加到 NSDictionary 对象中的底层实现了。
  • 为了提高效率, NSSet 和 NSDictionary 底层是使用 hash 表来实现的,所以当向其中添加对象时,它们会利用要添加的对象的 hash 值来查找判断该对象是否已经存在。
  • 在实现中,这个过程被分为两步:
  1. 先调用对象 hash 方法获取对象的 hash 值获对象在 hash 表的位置
  2. 如果找到了位置,也就是和目标 hash 值相等,就调用 isEqual: 判断两个对象内容是否相等。

4.总结

这个类东西不多,主要工作就是将 viewattr 封装成一个对象。

源码阅读:Masonry(三)—— MASViewAttribute的更多相关文章

  1. 【原】FMDB源码阅读(三)

    [原]FMDB源码阅读(三) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 FMDB比较优秀的地方就在于对多线程的处理.所以这一篇主要是研究FMDB的多线程处理的实现.而 ...

  2. 【原】AFNetworking源码阅读(三)

    [原]AFNetworking源码阅读(三) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇的话,主要是讲了如何通过构建一个request来生成一个data tas ...

  3. 【原】SDWebImage源码阅读(三)

    [原]SDWebImage源码阅读(三) 本文转载请注明出处 —— polobymulberry-博客园 1.SDWebImageDownloader中的downloadImageWithURL 我们 ...

  4. 【详解】ThreadPoolExecutor源码阅读(三)

    系列目录 [详解]ThreadPoolExecutor源码阅读(一) [详解]ThreadPoolExecutor源码阅读(二) [详解]ThreadPoolExecutor源码阅读(三) 线程数量的 ...

  5. Redis源码阅读(三)集群-连接初始化

    Redis源码阅读(三)集群-连接建立 对于并发请求很高的生产环境,单个Redis满足不了性能要求,通常都会配置Redis集群来提高服务性能.3.0之后的Redis支持了集群模式. Redis官方提供 ...

  6. SDWebImage源码阅读-第三篇

    这一篇讲讲不常用的一些方法. 1 sd_setImageWithPreviousCachedImageWithURL: placeholderImage: options: progress: com ...

  7. 【 js 基础 】【 源码学习 】backbone 源码阅读(三)浅谈 REST 和 CRUD

    最近看完了 backbone.js 的源码,这里对于源码的细节就不再赘述了,大家可以 star 我的源码阅读项目(https://github.com/JiayiLi/source-code-stud ...

  8. 【 js 基础 】【 源码学习 】backbone 源码阅读(三)

    最近看完了 backbone.js 的源码,这里对于源码的细节就不再赘述了,大家可以 star 我的源码阅读项目(https://github.com/JiayiLi/source-code-stud ...

  9. JDK源码阅读(三):ArraryList源码解析

    今天来看一下ArrayList的源码 目录 介绍 继承结构 属性 构造方法 add方法 remove方法 修改方法 获取元素 size()方法 isEmpty方法 clear方法 循环数组 1.介绍 ...

  10. LevelDB的源码阅读(三) Get操作

    在Linux上leveldb的安装和使用中我们写了这么一段测试代码,内容以及输出结果如下: #include <iostream> #include <string> #inc ...

随机推荐

  1. 经常登录Linux,用户密码背后的知识了解一下

    一,用户密码存放在哪里? 说到这个问题,绝大部分的同学肯定都知道/etc/passwd这个文件,不错,这个文件里存储的就是用户名,密码等信息. 每一行都是一个account,每一行有7个信息,分别用 ...

  2. Socket探索1-两种Socket服务端实现

    介绍 一次简单的Socket探索之旅,分别对Socket服务端的两种方式进行了测试和解析. CommonSocket 代码实现 实现一个简单的Socket服务,基本功能就是接收消息然后加上结束消息时间 ...

  3. php--一些新知识总结

    魔术方法__invoke() 当尝试以调用函数的方式调用一个对象时,__invoke() 方法会被自动调用 class Test { public function __invoke($a) { va ...

  4. 【数据库】MySQL数据库(二)

    一.数据库文件的导出 1.在DOS命令行下导出数据库(带数据) mysqldump -u root -p 数据库名 > E:\wamp\www\lamp175\lamp175.sql 2.在DO ...

  5. mpvue中使用flyjs全局拦截

    mpvue全局属性设置,在我之前的文章中有介绍,今天想记录的就是怎么和Fly.js结合使用来实现全局拦截功能: 首先我们要安装好Flyio,在mpvue项目中我们用npm下载安装: npm insta ...

  6. grub2手动引导linux

    仅需要三个命令 1.set root=(hd*,gpt*) hd*为系统所在磁盘,从0开始: gpt为磁盘分区表格式,*为第几分区,mbr分区表为msdos*: 2.linux /boot/vmlin ...

  7. 初始WebApi(1)

    如果你要问我WebApi是干嘛,我只能说它是的给数据.哈哈哈哈哈,这几天也才刚刚了解了解关于WebApi的知识,今天就来谈谈吧. 1.创建WebApi项目 第一步:选择ASP.NET Web应用程序 ...

  8. 一口气说出 4种 LBS “附近的人” 实现方式,面试官笑了

    引言 昨天一位公众号粉丝和我讨论了一道面试题,个人觉得比较有意义,这里整理了一下分享给大家,愿小伙伴们面试路上少踩坑.面试题目比较简单:"让你实现一个附近的人功能,你有什么方案?" ...

  9. Powershell基础---帮助系统

    帮助系统能带给我们什么? 1.快速找到命令,无需使用Bing或者Google 2.运行命令时候返回了错误信息,帮助系统可以告诉我们如何正确使用该命令 3.多个命令组合执行完成复杂的工作,帮助系统告诉我 ...

  10. Docker-Bridge Network 02 容器与外部通信

    本小节介绍bridge network模式下,容器与外部的通信. 1.前言2.容器访问外部2.1 访问外网2.2 原理2.3 一张图总结2.4 抓包3.外部访问容器3.1 创建nginx容器并从外部访 ...