【面试题】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];
}