iOS 메모리 관리(1)

계수식 메모리 관리를 참조하는 사고 방식:
4
  • 자신이 생성한 대상, 자신이 가지고 있는 것

  • 4
  • 자신이 생성한 대상이 아니면 자신도 소지할 수 있다

  • 4
  • 자신이 가진 대상이 더 이상 필요하지 않을 때 석방한다

  • 4
  • 자신이 보유한 대상이 아니면 석방할 수 없다

  • 객체 작업
    Objective-c 메서드
    객체 생성 및 보유
    alloc/new/copy/mutable Copy 방법
    소지 대상
    retain 메서드
    석방 대상
    release 방법
    객체 폐기
    dealloc 방법
    Cocoa 프레임워크의 Foundation 프레임워크의 NSObject 클래스는 메모리 관리 역할을 수행합니다.메모리 관리 중의 alloc/retain/release/dealloc 방법은 각각 NSObject 클래스의 alloc 클래스 방법,retain 실례 방법을 가리킨다.
    release 실례 방법과 dealloc 실례 방법.
     
    1. 자신이 생성한 대상, 자신이 가진 것
    다음 이름으로 시작하는 방법명은 자신이 생성한 대상이 자신만 가지고 있다는 것을 의미한다.   
  • alloc 
  • new
  • copy
  • mutaleCopy

  • 먼저 앞의 두 개: alloc new
     //  alloc              ,                 obj
            id obj = [[NSObject alloc] init];
            
            //  new             ,   alloc   new         
            id obj = [NSObject new];

    수정: 위 코드 주석에서 alloc와 new 두 가지는 완전히 일치한다고 말했는데 이런 견해는 정확하지 않습니다!사실은 [NSObject new]와 [NSObject alloc] init] 두 문장의 작용이 일치해야 한다.
     
    다음 두 개의 copy mutable Copy를 보겠습니다.
    이 두 사람의 이해는 좀 복잡하다.
    copy 방법은 NSCopying 방법에 근거하여 약정된 각종 실현된 copyWithZone: 방법으로 대상의 사본을 생성하고 보유한다.
    copy 방법과 유사하게mutableCopy 방법은 NSMutableCopying 방법을 바탕으로 약정하여 각종 실현된mutableCopyWithZone: 방법으로 대상의 사본을 생성하고 보유한다.
    차이점은 다음과 같습니다.
    copy 방법은 변경할 수 없는 대상을 생성하고mutableCopy 방법은 변경할 수 있는 대상을 생성합니다.(이렇게 말하면 약간 추상적일 수 있다. 다음은 하나의 예로 설명하자!)
            1. mutableCopy에서 새 가변 대상을 만들고 원 대상의 값으로 초기화하며 새 대상의 인용 계수는 1입니다.
            2. copy가 불변 객체를 반환합니다.두 가지 상황으로 나뉜다.
    (1) 원 대상이 변할 수 없는 대상이라면 원 대상으로 돌아가 인용 계수를 1로 추가한다.
    (2) 원래 대상이 가변 대상이라면 새로운 가변 대상을 만들고 원래 대상의 값으로 초기화하며 새 대상의 인용 계수는 1이다.
    //         
            NSArray *immutableArray = [[NSArray alloc] initWithObjects:@"one",@"two",@"three", nil];
            
            //                
            NSMutableArray *mutableArray = [immutableArray mutableCopy];
            [mutableArray addObject:@"four"];
            NSLog(@"count = %ld",(unsigned long)[mutableArray count]); //  : count = 4
    
            NSMutableArray *array = [[NSMutableArray alloc] init];
            array = [mutableArray copy];
            //      copy              ,      NSMutableArray  。                 ,      ,       。
            [array addObject:@"five"]; //    

    더 나아가 코피는 얕은 복사이고,mutable Copy는 깊은 복사이다.
    대상을 복사하는 것은 새로운 실례를 만들고 복사원의 값으로 초기화하는 것이다.
    boolean, 인덱스 같은 값에 대해 복사는 직접 값을 부여하는 것이다.
    바늘 모양의 Object는 얕은 복사와 깊은 복사로 나뉜다.얕은 복사는 하나의 새 포인터만 만들고 같은 데이터를 가리키는 것입니다.딥 카피는 데이터와 포인터를 모두 만드는 것이다.
    문외한: RetainCount라는 실례적인 방법을 통해 인용 계수 값을 관찰하려고 했는데 문제가 하나 발견됐습니다.
    NSObject* obj = [[NSObject alloc] init];
        NSLog(@"%li",(unsigned long)[obj retainCount]); // print: 1
        [obj release];
        NSLog(@"%li",(unsigned long)[obj retainCount]); // print: 1

    이 코드는 두 번 모두 출력 1이다.첫 번째 출력 1은 아무런 문제가 없을 것입니다. 왜냐하면 alloc는 인용 계수를 +1으로 하기 때문입니다.그리고release, 그럼 계수치-1을 인용하면 0을 출력해야 돼!이게 왜죠?
    사실 문제는 이렇다.
    먼저 RetainCount에 대해 설명한 내용을 살펴보겠습니다.
    Do not use this method. (required)
    This method is of no value in debugging memory management issues. Because any number of framework objects may have  retained an object in order to hold references to it, while at the same time autorelease pools may be holding any number of  deferred releases on an object, it is very unlikely that you can get useful information from this method.
    대략적인 의미는 이 방법은 debug 과정에서 아무런 가치가 없다는 것이다. (여러분은 사용하지 마세요) 시스템은 방출 대상을 늦추기 때문에 이 방법을 통해 유용한 정보를 얻을 수 없다.
    그래서?위의 마지막 문장은retainCount를 통해 인용 계수 값을 출력하여 얻은 정보는 정확하지 않다. 사실은 이미 대상을 방출했고 시스템이 시간을 늦추어 방출했을 뿐이다.마지막 출력문이 실행될 때
    후,obj라는 대상은 사실 아직 방출되지 않았다(인용계수값은 아직 0이 아니다). 만약 0과 같다면 시스템은 직접 대상을 폐기하지 않았을까?그럼 리타인 카운트라는 실례를 어떻게 호출할 수 있겠어?
    release 문장을 추가하면 프로그램이 붕괴됩니다. 그렇지 않으면have a try!이건 내 이해야.
    2. 자신이 생성하지 않은 대상은 자신도 가질 수 있다
    alloc new copy mutable Copy 이외의 방법으로 얻은 대상은 대상이 자신이 생성하지 않기 때문에 모든 대상은 자신이 가지고 있지 않지만 대상의 존재를 얻을 수 있습니다.
    //       ,          
        id obj = [NSMutableArray array];
        
        //  retain      
        [obj retain];

    그러면 retain 방법을 통해 자신이 생성하지 않은 대상도 스스로 보유할 수 있다. 마치 alloc new copy mutable Copy 방법으로 대상을 생성하고 보유한 것과 같다.
    3. 자신이 가진 대상이 더 이상 필요하지 않을 때 석방
    자신이 보유한 대상은 필요하지 않으면 소지자는 해당 대상을 풀어주고release 방법을 사용할 의무가 있다.
    UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(10, 10, 100, 100)];
        [label release];
        //       ,      
        label.text = @"hello world";
        //      

    4、
    만약에 어떤 방법으로 대상을 생성하고 이를 이 방법의 호출자에게 돌려주고 호출자가 대상을 가지도록 하려면 어떻게 실현합니까?
    -(id)allocObject {
        id obj = [[NSObject alloc]init];
        return obj;
    }

    주의 방법의 명칭 규칙은 alloc new copy mutable Copy로 시작합니다.
    그렇다면 어떤 방법으로 대상의 존재를 얻고 싶지만 자신이 대상을 가지고 있지 않다면 어떻게 실현해야 하는가?
    -(id)object {
        id obj = [[NSObject alloc]init]; //      
        
        [obj autorelease]; //       ,         
        
        return obj;
    }

    대상이 없기 때문에 alloc new copy mutable Copy로 시작하지 않도록 주의하십시오.
    위에서 autorelease 방법을 사용했는데 이 방법으로 대상의 존재를 얻을 수 있으나 자신은 대상을 가지고 있지 않다.autorelease는 대상이 지정한 생존 범위를 초과할 때 자동으로 정확하게 방출될 수 있도록 합니다.
    release 방법).
    [obj autorelease]; 이 문장은obj 대상을 autoreleasepool (자동 방출 버퍼) 에 등록하고 pool이 끝날 때release 방법을 자동으로 호출합니다.이렇게 이해하면 autoreleasepool이 대상을 가지고 책임 대상의 방출을 맡게 할 수 있다.
    방법 호출
    id obj1 = [self allocObject]; //      
        
        id obj2 = [self object]; //       ,        
        //       retain       
        [obj2 retain];

    5、자신이 보유한 대상이 아니면 석방할 수 없습니다
    alloc new copy mutable Copy 방법으로 생성하고 보유한 대상이나retain 방법으로 보유한 대상은 보유자가 모두 자신이기 때문에 대상이 필요하지 않을 때release를 호출하여 대상을 방출한다.
    이외에 얻은 대상은 절대 방출할 수 없다. 만약 프로그램에서 자신이 가지고 있지 않은 대상을 방출한다면 붕괴를 초래할 것이다.
    //   1
        id obj1 = [self allocObject]; //      
        [obj1 release]; //       
        [obj1 release]; //             ,          ,    
        
        //   2
        id obj2 = [self object]; //       ,        
        [obj2 release]; //          ,    

    여기 있는 allocObject 방법은 object 방법과 같습니다.
    6. 인용 계수 값을 이용하여 메모리 관리를 실현한다.
    4
  • Objective-c의 대상에 인용 계수가 저장되어 있습니다

  • 4
  • retain 또는 alloc new copy mutable Copy 방법을 호출하고 계수값 +1을 참조합니다

  • 4
  • release를 호출한 후 계수값-1을 인용한다

  • 4
  • 인용 계수 값이 0일 때 dealloc 방법으로 대상을 폐기합니다

  • 7、autorelease 
    autorelease는 C 언어의 자동 변수 (국부 변수) 와 유사한 자동 방출입니다.
    c 언어에서 자동 변수는 프로그램 실행 과정에서 작용역을 초과하면 자동으로 폐기됩니다.그러면 같은 이치로 autorelease는 c 언어의 자동 변수처럼 실례 대상을 대할 것이다.작용역을 초과할 때,
    대상 실례의release 방법이 자동으로 호출됩니다.
    사용 방법은 다음과 같습니다.
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; //     NSAutoreleasePool  
        id obj = [[NSObject alloc] init]; 
        [obj autorelease]; //           autorelease
        [pool drain]; //   NSAutoreleasePool  

    마지막 줄의 [pool drain];[poolrelease]와 같다.
    이 글도 《objective-c 고급 프로그래밍ios와osx 다중 루틴과 메모리 관리》를 참고할 때 기록을 베껴 정리한 것이다.메모리 관리를 배우기 시작한 것이 첫 번째 기록이다.

    좋은 웹페이지 즐겨찾기