专题:临时区iOS DeveloperiOS-周边收集

【面试题】masonry为什么没有导致循环引用?

2017-04-21  本文已影响559人  不上火喝纯净水

我要说:鉴于,这个问题过于简单,中高级请略过此文,以下仅针对初初级iOS开发人员:

Masonry是一个轻量级的自动布局框架,在iOS开发界被广泛采用,先看如下代码

    @weakify(self);
    [self.mainTable mas_makeConstraints:^(MASConstraintMaker *make) {
        @strongify(self);
        make.top.(self.view)).offset(100);
        make.left.right.bottom.equalTo(self.view);
    }];

为了避免出现block的循环引用,我们已经养成了很好的习惯,weak/strong破除循环引用,更简单的是借用RAC中定义的@weakify/@strongify这对宏,几乎针对所有的block我们都可以使用如下方法来避免循环引用。

这么写没有任何问题,只是我们要知道这里并不存在循环引用问题,所有完全没有必要使用weak/strong来破除循环引用。虽然block块内确实对调用对象有强引用,block的变量捕捉会使得调用对象引用计数+1.但是block循环引用的前提条件是调用对象直接或者间接对block持有强引用。而masonry的block方法实现中并不涉及。

查看masonry源码可以看到究竟:masonry中设置布局的方法中的block对象并没有被View所引用,而是直接在方法内部同步执行,执行完以后block将释放,其中捕捉的外部变量的引用计数也将还原到之前。

//
//  UIView+MASAdditions.m
//  Masonry
//
//  Created by Jonas Budelmann on 20/07/13.
//  Copyright (c) 2013 cloudling. All rights reserved.
//

#import "View+MASAdditions.h"
#import <objc/runtime.h>

@implementation MAS_VIEW (MASAdditions)

- (NSArray *)mas_makeConstraints:(void(^)(MASConstraintMaker *))block {
    self.translatesAutoresizingMaskIntoConstraints = NO;
    MASConstraintMaker *constraintMaker = [[MASConstraintMaker alloc] initWithView:self];
    block(constraintMaker);
    return [constraintMaker install];
}

- (NSArray *)mas_updateConstraints:(void(^)(MASConstraintMaker *))block {
    self.translatesAutoresizingMaskIntoConstraints = NO;
    MASConstraintMaker *constraintMaker = [[MASConstraintMaker alloc] initWithView:self];
    constraintMaker.updateExisting = YES;
    block(constraintMaker);
    return [constraintMaker install];
}

- (NSArray *)mas_remakeConstraints:(void(^)(MASConstraintMaker *make))block {
    self.translatesAutoresizingMaskIntoConstraints = NO;
    MASConstraintMaker *constraintMaker = [[MASConstraintMaker alloc] initWithView:self];
    constraintMaker.removeExisting = YES;
    block(constraintMaker);
    return [constraintMaker install];
}
上一篇下一篇

猜你喜欢

热点阅读