自动布局-SDAutoLayout

一、简介

SDAutoLayout是基于对frame进行设置的一直布局,被依赖的view布局要写在前面,不然有可能造成界面异常(或者布局后面添加[被依赖的view updateLayout],手动进行刷新)

二、原理

view是没有sd_layout属性的,作者使用动态关联,扩展UIView, 调用getter方法时sd_layout对象生成,此对象作为view对象的布局控制模块, 每次生成一个sd_layout对象,都把它加为super viewautolayoutModelsArray中,sd_layout对象即SDAutoLyaout的实例,SDAutoLayout下设left, top, bottom, right等对象负责具体的布局... 用文字解释不了,看个图:

可见作者的面向对象思想是相当牛B的。

当我们调用 view.sd_layout.leftSpaceToView(self.view, 20) 时,sd_layout 对象的leftSpaceToView 是个懒加载的block, 我们这样是调用这个block, 这样在内部SDAutoLayout对frame进行赋值,所以,SDAutoLayout并不像其名字AutoLayout所示通过NSLayoutConstraint来对view进行布局的,它是本质上通过修改视图的frame来处理的。

继续:当调用[someView updateLayout]的时候,我们顺着API找下去:

// UIView的Category中:
- (void)updateLayout
{
    [self.superview layoutSubviews];
}

也就是说,当对一个view updateLayout的时候,它会调其父视图的layoutSubviews, 而当调用layoutSubviews时,SDAutoLayout使用方法交换,调用sd_layoutSubviews,我们可以看到交换方法的源代码:

+ (void)load
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{

        NSArray *selStringsArray = @[@"setText:"];

        [selStringsArray enumerateObjectsUsingBlock:^(NSString *selString, NSUInteger idx, BOOL *stop) {
            NSString *mySelString = [@"sd_" stringByAppendingString:selString];

            Method originalMethod = class_getInstanceMethod(self, NSSelectorFromString(selString));
            Method myMethod = class_getInstanceMethod(self, NSSelectorFromString(mySelString));
            method_exchangeImplementations(originalMethod, myMethod);
        }];
    });
}

调用sd_layoutSubviews

// UIView的Category中:
- (void)sd_layoutSubviews
{
    [self sd_layoutSubviews]; // 此处由于方法交换,调用[self layoutSubviews]   
    [self sd_layoutSubviewsHandle];
}

sd_layoutSubviewsHandle中,我们知道,看上面图中视图有一个autolayoutModelsArray,它记录着其所有子视图用SDAutoLayout布局的对象,并可以找到每一个子视图所关联着的SDAutoLayout对象,所它来布局。上面谈到,在SDAutoLayout中有left, top, bottom, right等具体的对象,在这些对象中都有一个refView代表其所参照的视图,我们可以把它想像成链表,链表的上一个节点动了,其被参照的视图根据refView找到前一个节点,从而作刷新。

三、实现

参考github上的Demo

借鉴愤怒的振振的文章https://www.jianshu.com/p/2ddf29e029fe

你可能感兴趣的:(自动布局-SDAutoLayout)