[면접문제] 마스토리는 왜 순환 인용을 초래하지 않았나요?

2239 단어
이 문제가 너무 간단하다는 점을 감안하여 중급자는 이 글을 생략하고 다음은 초급 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 

@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];
}

좋은 웹페이지 즐겨찾기