autorelease와 autoreleasepool

5392 단어
MRC 환경에서 대상의 방출은 수동[obj release] 방법으로 대상의 인용 계수를 1로 줄여야 한다.release 방법을 호출한 후 이 대상의 인용 계수는 즉시 1 감소[obj autorelease]release의 차이점은 대상의 인용 계수를 즉시 1로 줄이지 않고 대상의 방출을 늦추는 것이다.
그럼 언제까지 늦춰요?autorelease 대상은 즉시 release조작을 하지 않으며, 이 대상이 있는 곳autoreleasepool이 소각될 때 이 대상은 release조작을 한다.
그럼 이 대상은 어디에 추가되었는지autoreleasepool, 이autoreleasepool는 언제 풀려날까요?
대상이 만들어지면 기본적으로 시스템 유지보수autoreleasepool에 추가됩니다.
그럼 시스템 유지 보수하는 이거autoreleasepool는 언제 풀려요?
시스템 유지보수autoreleasepool의 방출 시기에 대해 라인,runloop과autoreleasepool의 관계를 알아야 한다.
각 스레드마다 주 스레드를 포함하여 NSRunLoop 대상이 하나씩 있다.간단하게 이runloop을 사순환으로 볼 수 있다. 이runloop은 끊임없이 사건을 접수하고 사건을 처리한다.순환이 시작될 때마다 자동으로 생성됩니다. autoreleasepool순환이 끝날 때drain을 한 번 진행하면 autoreleasepool의 모든 대상이release 작업을 한 번 합니다.그래서 시스템 유지보수의 autoreleasepool은runloop의 한 주기가 끝날 때 방출된다.stringWithFormat autorelease 대상을 되돌려줍니다

case one

__weak id reference = nil;
- (void)viewDidLoad {
    [super viewDidLoad];
    NSString *str = [NSString stringWithFormat:@"a string object"];
    reference = str;
    NSLog(@"viewDidLoad - %@", reference);
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    NSLog(@"viewWillAppear - %@", reference);
}

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    NSLog(@"viewDidAppear - %@", reference);
}

결과 내보내기
viewDidLoad - a string object
viewWillAppear - a string object
viewDidAppear - (null)

코드 분석reference 약한 인용strstr의 인용 계수에 영향을 주지 않으며 str가 풀렸는지 확인하는 데 사용됩니다.[NSString stringWithFormat:@"a string object"] 문자열 대상을 만듭니다. 이 대상의 인용 계수는 1입니다.autorelease를 통해 이 문자열의 대상을 인용하면 인용 계수가 2로 변합니다str 방법 실행 완료, viewDidLoad 바늘 방출, 문자열 대상의 인용 계수 1strdrain시 문자열 대상autoreleasepool작업을 진행하고 인용계수를 0으로 변경하여 이 대상을 삭제합니다
출력 결과에서 알 수 있듯이 시스템이 유지보수하는 autoreleasepool은 release할 때drain 조작을 하지 않았고 viewWillAppear할 때drain 조작을 실행하여 문자열의 대상이 방출되었다.
이 경우 시스템 기본값viewDidAppear에 가입

case two

__weak id reference = nil;
- (void)viewDidLoad {
    [super viewDidLoad];
    @autoreleasepool {
        NSString *str = [NSString stringWithFormat:@"a string object"];
        reference = str;
    }
    NSLog(@"viewDidLoad - %@", reference);
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    NSLog(@"viewWillAppear - %@", reference);
}

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    NSLog(@"viewDidAppear - %@", reference);
}


결과 내보내기
viewDidLoad - (null)
viewWillAppear - (null)
viewDidAppear - (null)

코드 분석autoreleasepool 에서 viewDidLoad 자동 풀을 직접 생성@autoreleasepool{} 작용역이 나오면 @autoreleasepool{}drain에 의해 내부 문자열의 대상release가 됩니다.인용 계수 1 감소autoreleasepool 작용역을 벗어나면 국부 변수str가 삭제되고 문자열 대상의 인용 계수가 1로 줄어들어 0이 됩니다.문자열이 제거됩니다.그래서 레퍼런스 실행이nil로 바뀌었어요.

case three

__weak id reference = nil;
- (void)viewDidLoad {
    [super viewDidLoad];
    NSString *str = nil;
    @autoreleasepool {
        str = [NSString stringWithFormat:@"a string object"];
        reference = str;
    }
    NSLog(@"viewDidLoad - %@", reference);
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    NSLog(@"viewWillAppear - %@", reference);
}

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    NSLog(@"viewDidAppear - %@", reference);
}

결과 내보내기

viewDidLoad - a string object
viewWillAppear - (null)
viewDidAppear - (null)

코드 분석


두 번째 상황에 비해 @autoreleasepool{} 변수를 str의 바깥쪽에 두었기 때문에 @autoreleasepool{} 이후 문자열 대상은release가 한 번 했지만 @autoreleasepool{}는 이 대상을 인용하고 있다.그래서 str에서 풀리지 않았다.viewDidLoad 이후 viewDidLoad 변수가 삭제되고 문자열에 대한 인용이 없으면 문자열의 대상이 방출됩니다.

autoreleasepool 언제 주동적으로 사용

for (int i = 0; i < 1000; i++) {
    NSString *var = [NSString stringWithFormat:@""];
}

순환 중 대량의 autorelease 대상이 발생하면, 이 대상들은 순환이 끝난 후에 바로 방출되지 않습니다.위 예에서 이 1000개의 문자열 대상은 이번runloop이 끝날 때까지 풀리지 않습니다.짧은 시간에 과도한 메모리를 초래하다.
for (int i = 0; i < 1000; i++) {
    @autoreleasepool {
        NSString *var = [NSString stringWithFormat:@""];
    }
}

autoreleasepool을 사용한 후 순환이 끝날 때마다 autoreleasepool의 작용역이 끝나면 이 대상은 바로 방출됩니다.메모리의 과도한 증가를 피하다.

어떤 대상이 기본적으로 autorelease인지


보통 비str,alloc,new,copy에 나오는 대상은 모두 autorelease의것이다. 예를 들어mutableCopy,[UIImage imageNamed:],[NSString stringWithFormat] 등이다.
확실하지 않을 때caseone을 통해 이 대상이 작용역이 끝난 후에 방출을 이해하는지 확인할 수 있습니다.

참조 링크

  • http://www.cocoachina.com/ios/20150610/12093.html
  • 좋은 웹페이지 즐겨찾기