Objective-C의 메모리 관리(2) - MRC에서 ARC로

5147 단어 objective-cios
자질구레한 단순한 개인 필기.

MRC


인용 계수 전편은 이미 대략적으로 말한 적이 있다.Objective-C에서는 NSObject에서 상속된 모든 대상이 자신의 인용 계수를 기록하고 가감한 후에 0이 되면 방출된다.MRC는 Mannul Reference Counting의 약자로 의미도 간단하며 이번 플러스 마이너스는 모두 수동으로 관리한다는 뜻이다.
사용할 때의 기본 원칙은 자신을 잘 관리하는 것이다.대상마다 다른 대상을 인용할 때 몇 번의 계수를 덧붙여 결국 사용하지 않을 때가 되면 몇 번씩 줄여야 한다.많으면 안 되고 적으면 안 된다.이렇게 해서 많은 초점을 맞췄다.
인용 계수가 증가하는 동작은 현식적인retain은 많지 않다. 나머지는 네 개의 키워드: alloc, new(그리고 new로 시작하는 방법),copy,mutableCopy이다. 이 네 개의 키워드를 사용하여 얻은 대상은 네가 추가한 인용 계수를 나중에 스스로 줄여야 한다.
인용 계수가 줄어드는 조작이release입니다.

AutoRelease


AutoReleasePool은 자동 해제 풀로 그 안에 가입한 대상은 Pool이'끝'될 때까지 방출됩니다.MRC에서는 객체를 명시적으로 추가하고 AutoReleasePool을 명시적으로 해제하는 NSAutoReleasePool을 명시적으로 생성할 수 있습니다.
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// Code benefitting from a local autorelease pool.
NSObject *obj = [[[NSObject alloc] init] autorelease];
[pool release];//[pool drain];
ARC에서는
@autoreleasepool {
    // Code benefitting from a local autorelease pool.
}
기본적으로 모든 Runloop 교체가 시작될 때 AutoReleasePool을 만들고 Runloop 교체가 끝날 때 방출합니다.즉, AutoReleasePool을 현저하게 만들지 않았을 때 autorelease의 대상은 Runloop 교체가 끝날 때 방출된다는 것이다.AutoReleasePool을 현저하게 만들 때, 그 방출 시기는 우리가 결정합니다. (release/drain 또는 Block을 현저하게 호출해서 끝냅니다.)
AutoReleasePool을 능동적으로 사용하는 목적은 일반적으로 메모리 피크를 제어하기 위한 것입니다.예를 들어, 나는 큰 순환이 있는데, 매번 순환할 때마다 비교적 큰 autorelease의 임시 대상을 만들 것이다.만약 명시적으로 방출되지 않는다면, 이 임시 대상들은 전체 순환이 끝난 후에야 함께 방출될 것이며, 그 동안 메모리가 너무 많이 사용될 수 있다.이 경우 매번 순환 내에서autoreleasepool을 성명하여 임시 대상이 쌓이지 않도록 보증할 수 있다.

ARC


ARC는 우리를 위해 자동적으로 많은 것을 하고 많은 세부 사항을 차단했다. 이론적으로 우리는 대상 간의 소유권 관계에 주목하기만 하면 된다.상부의 메커니즘은 간단하지만 관련된 세부 사항이 매우 많다. 축하할 만한 것은 ARC가 표준 문서가 있다는 것이다.그야말로..
ARC에서 제공하는 변수 수정자는 다음과 같습니다.
  • __strong
  • __weak
  • __unsafe_unretaied
  • __autoreleasing
  • 제공되는 속성 수정자는 다음과 같습니다.
  • assign에 해당하는 소유권 유형은unsafe_unretained.
  • copy에 해당하는 소유권 유형은strong.
  • retain에 대응하는 소유권 유형은strong.
  • strong에 대응하는 소유권 유형은strong.
  • unsafe_unretained에 대응하는 소유권 유형은 입니다unsafe_unretained.
  • weak에 대응하는 소유권 유형은weak.
  • (기본 유형 기본값은assign, 대상 유형 기본값은strong)

    __strong


    억지로 인용하여 더 이상 말하지 않겠다.변수와 속성을 설명할 때 설명을 하지 않으면 기본적으로 강제 인용입니다.

    __weak


    약인용.대상이 풀리면 weak 수식의 변수는nil로 설정됩니다.이 특성을 실현하려면 모든 weak 변수를 하나의 전체적인 맵에 넣어야 하기 때문에 실현 원가가 비교적 높다.

    __unsafe_unretained


    어떠한 추가 조작도 하지 않는다.

    __autoreleasing


    __autoreleasing 표시의 변수는 autorelease 방법을 호출하는 것과 같습니다
    작은 문제가 생각났다. 함수 반환값에 대해 ARC는 인용계수를 넣을지 말지 어떻게 알았을까?이 몇 줄의 코드를 보십시오:
    - (void)testMethod
    {
        NSObject *obj = [NSObject new];
        NSArray *array = [NSArray array];
        // do something
    }
    ARC에서 obj와 array가 다 쓴 후에 자동으로 방출되지만 자세히 생각해 보면 디테일이 적지 않다.[NSObject new]에서 반환되는 객체 참조 수는 +1이고 [NSArray array]가 아니라는 것을 알아야 합니다.이 두 장난감은 인용 계수가 1이 모자랐는데, ARC는 누가 한 번 더 풀어야 하는지 어떻게 알았습니까?MRC에서 우리는 new에 나오는 obj는 수동으로 풀어야 하고 array는 필요 없다는 것을 알고 방법의 키워드를 통해 판단한다.그런데 방법 중의 키워드는 어떤 약속이 아닐까요?ARC도 혹시 new로 시작하는 방법이 있는지 보러 갈까요?문서를 보니까...ARC가 진짜 이렇게 했는데...
    Methods in the alloc, copy, init, mutableCopy, and new families are implicitly marked __attribute__((ns_returns_retained)).
    돌이켜보면 MRC 시대에 이런 키워드들은 약속에서 멈춰야 한다.ARC는 매끄러운 과도를 위해 약속했던 것을 문법규범으로 바꾸었을지도 몰라요. emmm, 이렇게 하는 것은 좋지 않은 것 같아요.

    블록 메모리 관리


    ARC 이후 메모리 관리 문제는 많이 줄어들었지만 여전히 남아 있다.그 중 가장 중요한 부분은 블록과 관련된 메모리 관리다.Objective-C에서 Block의 반복 참조 문제 참조

    Bridge


    Core Foundation 프레임워크(Core Foundation.framework)는 iOS 응용 프로그램에 기본 데이터 관리와 서비스 기능을 제공하는 C 언어 인터페이스이다.Objective-C 객체 및 CF 객체는 직접 변환할 수 있습니다.
    CFStringRef aCFString = (CFStringRef)aNSString;
    NSString *aNSString = (NSString *)aCFString;
    그러나 ARC는 CF 대상의 메모리 관리를 지원하지 않기 때문에 전환된 대상을 누가 방출할지 주목해야 한다.
    MRC에서는 비교적 간단하며 CFRelease와release 방법은 같은 효과가 있기 때문에 기회를 선택하여 사용하면 된다.여기서는 주로 ARC 하의 상황을 주목한다.수요에 따라 3가지 전환 방식이 있다
  • __bridge (대상 소유권 변경 없음)
  • __bridge_retained 또는 CFBridgingRetain()(ARC 소유권 해제)
  • __bridge_transfer 또는 CFBridgingRelease()(ARC 소유권 부여)
  • 1. __bridge


    __bridge는 대상의 소유권을 바꾸지 않습니다.
  • OC 대상이 CF로 전환되고 ARC가 관리하며 명시적으로 방출할 필요가 없음
  • NSString *aNSString = [[NSString alloc]initWithFormat:@"test"];
    CFStringRef aCFString = (__bridge CFStringRef)aNSString;
    // do something
  • CF 대상이 OC로 전환되고 CF가 관리하며 명시적 방출이 필요하다
  • CFStringRef aCFString = CFStringCreateWithCString(NULL, "test", kCFStringEncodingASCII);
    NSString *aNSString = (__bridge NSString *)aCFString;
    // do something
    CFRelease(aCFString);

    2. __bridge_retained


    CF에 대한 소유권이므로 CFRelease를 호출하여 명시적으로 석방해야 합니다.
    NSString *aNSString = [[NSString alloc]initWithFormat:@"test"];
    CFStringRef aCFString = (__bridge_retained CFStringRef) aNSString;
    // do something
    CFRelease(aCFString); 

    3. __bridge_transfer


    ARC에 소유권을 부여하므로 수동으로 관리할 필요가 없습니다.
    CFStringRef aCFString = CFStringCreateWithCString(NULL, "test", kCFStringEncodingASCII);
    NSString *aNSString = (__bridge_transfer NSString *)aCFString;
    // do something

    좋은 웹페이지 즐겨찾기