문제

나는 무언가를 명확히하고 싶었다.

다음 코드가 있다고 가정 해 봅시다.

- (void) viewDidAppear:(BOOL)animated {
  [super viewDidAppear:animated];
  for (int i = 0; i < 5000000; i++) {
    NSString *s = [NSString stringWithFormat:@"Hello, %@!", @"World"];
  }
}

이 기능 호출 내에서 5 백만 개의 자동 엘라스 문자열이 생성됩니다. 내가 보는 유일한 @autoreleasepool은 Main.M. 그래도 그렇지 않습니다. 이 기능 호출이 끝나면 모두 릴리스를 호출하고 메모리에서 제거하는 것 같습니다.

이 문서:

https://developer.apple.com/library/mac/documentation/cocoa/reference/foundation/classes/nsautoreleasepool_class/reference/reference.html

"애플리케이션 키트는 이벤트 루프의 모든 사이클의 시작 부분에서 기본 스레드에 자동 제출 풀을 생성하고 끝에 배출하여 이벤트를 처리하는 동안 생성 된 자동 저리체 객체를 공개합니다."

그것은 나에게 의미가 있지만 이것은 응용 프로그램 키트가 아니라 Uikit 아래에 있습니다. 내 질문은,이 경우 Uikit/Cocoa Touch가 똑같은 일을합니까, 아니면 내 객체가 출시되는 것에 대한 또 다른 설명이 있습니까?

감사!

도움이 되었습니까?

해결책 2

예, Uikit도 같은 일을합니다. 시스템이 만든 메인 스레드 자동 제출 풀은 모든 런 루프 사이클의 끝에 배수됩니다. 자신의 코드 에서이 정확한 수명에 의존하지 않는 것이 가장 좋습니다. 새 스레드를 수동으로 만들면 (예 : NSTHREAD를 사용하여) 해당 스레드에서 자동 제출 풀을 작성해야합니다.

편집 : Rob의 답변은 ARC의 행동에 관한 좋은 추가 정보를 제공합니다. 일반적으로, 일부 최적화 아크가 만들 수 있기 때문에 물체가 자동 제국 풀에서 끝날 가능성이 적다는 것은 공평합니다.

다른 팁

Andrew는 메인 런 루프의 모든주기마다 자동 제국 풀이 배수 될 것이라는 주요 질문에 대답했습니다. 따라서 생성 된 모든 자동 제출 객체 viewDidLoad 메인 런 루프로 돌아갈 때 즉시 배수 될 수 있습니다. 그들은 확실히 "신청이 종료 될 때까지"유지되지 않을 것입니다.

그러나 우리는 조심해야합니다. 이러한 객체가 자동 제국 풀에 추가되고 있다고 가정합니다. 이 가정에 대한 몇 가지 경고 :

  1. 이름이 시작되지 않은 메소드에서 객체를 반환 할 때 과거 (및 ARC-MRC 상호 운용성에 여전히 필요). alloc, new, copy, 또는 mutableCopy, 이러한 객체는 자동 제출 풀이 배수 된 경우에만 거래되며 (즉, 런 루프로 다시 산출 할 때).

  2. 그러나 Arc는 자동 제출 풀의 필요성을 최소화하는 것에 대해 더 똑똑해졌습니다 ( http://rentzsch.tumblr.com/post/75082194868/arcs-fast-autorelease, 논의합니다 callerAcceptsFastAutorelease, 이제 callerAcceptsOptimizedReturn 발병 prepareOptimizedReturn), 그래서 당신은 종종 이것을 보지 못할 것입니다 autorelease 행동. 따라서 라이브러리와 발신자가 모두 ARC를 사용하는 경우 AutorELEASE 풀에 객체가 배치되지 않을 수 있지만 ARC는 필요하지 않은 경우 즉시 즉시 해제됩니다.

    현대적인 아크 프로젝트를 사용하면 일반적으로 자동 제국 풀이 필요하지 않습니다. 그러나 어떤 특별한 경우에도 여전히 자동 제출 풀을 사용하면 혜택을 볼 수 있습니다. 아래의 사례 중 하나를 설명하겠습니다.

다음 코드를 고려하십시오.

#import "ViewController.h"
#import <sys/kdebug_signpost.h>

typedef enum : NSUInteger {
    InnerLoop = 1,
    MainLoop = 2
} MySignPostCodes;

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    NSURL *fileURL = [[NSBundle mainBundle] URLForResource:@"test" withExtension:@"png"];
    
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        kdebug_signpost_start(MainLoop, 0, 0, 0, 1);
        for (int j = 0; j < 500; i++) {
            NSData *data = [NSData dataWithContentsOfURL:fileURL];
            UIImage *image = [[UIImage alloc] initWithData:data];
            NSLog(@"%p", NSStringFromCGSize(image.size));  // so it's not optimized out
            [NSThread sleepForTimeInterval:0.01];
        }
        kdebug_signpost_end(MainLoop, 0, 0, 0, 1);
    });
}

@end

다음 코드는 AutoreLease Pool에 50 만 개 객체를 추가하며, 이는 런 루프로 다시 양보 할 때만 배수됩니다.

no pool

이 경우 자동 수원 풀을 사용하여 높은 수상을 최소화 할 수 있습니다.

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    NSURL *fileURL = [[NSBundle mainBundle] URLForResource:@"test" withExtension:@"png"];
    
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        kdebug_signpost_start(MainLoop, 0, 0, 0, 1);
        for (int j = 0; j < 5; j++) {
            @autoreleasepool {
                kdebug_signpost_start(InnerLoop, 0, 0, 0, 2);
                for (long i = 0; i < 100; i++) {
                    NSData *data = [NSData dataWithContentsOfURL:fileURL];
                    UIImage *image = [[UIImage alloc] initWithData:data];
                    NSLog(@"%p", NSStringFromCGSize(image.size));  // so it's not optimized out
                    [NSThread sleepForTimeInterval:0.01];
                }
                kdebug_signpost_end(InnerLoop, 0, 0, 0, 2);
            }
        }
        kdebug_signpost_end(MainLoop, 0, 0, 0, 1);
    });
}

@end

pool

결론, ARC를 사용하면 AutorELEASE 객체를 사용했을 때 항상 변수가 범위에서 벗어날 때 명시 적으로 공개 할 때 항상 분명하지는 않습니다. 악기의 동작을 검사하여 언제든지 확인할 수 있습니다.

제쳐두고, 나는 사용할 때 너무 많은 일반 메모리 관리 결론을 도출하는 것에 대해 조심할 것입니다. NSString 클래스는 최적화되었으며 항상 표준 메모리 관리 관행을 준수하지는 않습니다.

나는 당신이 객체를 보유하는 데 사용 된 참조에 새 개체를 할당 할 때 원래 객체는 즉시 해제됩니다 (다른 것을 가리키지 않으면 - 심판 수는 0으로갑니다) Arc와 Asuming default를 사용합니다. strong 루프 예제에서와 같이 참조하십시오.

MyObject *object = [[MyObject alloc] init]; // obj1, ref count 1 because strong
object = [[MyObject alloc] init]; // obj2, ref count of obj1 should be 0
                                  // so obj1 gets released

Apple Notes 아크 릴리스 노트로 전환

유지/릴리스 호출이 어디에 있는지 생각하지 말고 대신 응용 프로그램 알고리즘에 대해 생각하십시오. 대상의 "강하고 약한"포인터, 객체 소유권 및 가능한 유지주기에 대해 생각해보십시오.

그게 들린다 release Clang에서 새 값이 할당 될 때 객체에서 호출됩니다. Clang 3.4 문서화 Objective-C 자동 참조 계산 (ARC)

과제는 할당 연산자를 평가할 때 발생합니다. 의미론은 자격에 따라 다릅니다.

__strong 물체의 경우, 새로운 지점이 먼저 유지됩니다. 둘째, LValue에는 원시 의미론이 장착되어 있습니다. 셋째, 새로운 포인트는 원시 의미론으로 LValue에 저장됩니다. 그리고 마지막으로, 오래된 지점이 풀려납니다. 이것은 원자 적으로 수행되지 않습니다. 외부 동기화는 동시 부하 및 상점에 직면하여 안전하게 만들기 위해 사용해야합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top