• 源码阅读:Masonry(三)—— MASViewAttribute


    该文章阅读的 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 封装成一个对象。

  • 相关阅读:
    Android之Parcel
    Android常用的IPC通信
    Android之Surface绘制原理
    Android之Surface
    Android之SurfaceFlinger服务
    Android Service(服务)
    Android Service进阶之路
    Android之UI线程启动
    Android之Activity显示原理
    python17-Django进阶
  • 原文地址:https://www.cnblogs.com/twodog/p/12136265.html
Copyright © 2020-2023  润新知