티스토리 뷰

소유권 수식어

Objective-C

다음과 같은 수식어를 사용 할 수 있다.

 

__strong

 - 강한참조, 해당 수식어를 가진 포인터로 객체를 참조하게되면 retain count가 1증가한다.

__weak

 - 약한참조, 해당 수식어를 가진 포인터로 객체를 참조하여도 retain count가 증가하지않는다.

__unsafe_unretained

 - 약한참조, 해당 수식으를 가진 포인터로 객체를 참조하여도 retain count가 증가하지않는다.

__autoreleasing

 - 오토릴리즈를 객체의 수식어로 붙혀준다.

 

예제

__strong

id __strong obj1 = [[NSObject alloc] init];
id __strong obj2 = obj1;
NSLog(@"log1:%@",obj1);
NSLog(@"log2:%@",obj2);
obj1 = nil;
NSLog(@"log3:%@",obj1);
NSLog(@"log4:%@",obj2);

__strong 결과

2021-03-14 14:54:52.735758+0900 ARC_MemorySample_Ojbc[40372:360247] log1:<NSObject: 0x600002ddc9f0>
2021-03-14 14:54:52.735855+0900 ARC_MemorySample_Ojbc[40372:360247] log2:<NSObject: 0x600002ddc9f0>
2021-03-14 14:54:52.735926+0900 ARC_MemorySample_Ojbc[40372:360247] log3:(null)
2021-03-14 14:54:52.736001+0900 ARC_MemorySample_Ojbc[40372:360247] log4:<NSObject: 0x600002ddc9f0>

__weak 

id __strong obj1 = [[NSObject alloc] init];
id __weak obj2 = obj1;
NSLog(@"log1:%@",obj1);
NSLog(@"log2:%@",obj2);
obj1 = nil;
NSLog(@"log3:%@",obj1);
NSLog(@"log4:%@",obj2);

__weak 결과 

2021-03-14 14:54:52.735758+0900 ARC_MemorySample_Ojbc[40372:360247] log1:<NSObject: 0x600002ddc9f0>
2021-03-14 14:54:52.735855+0900 ARC_MemorySample_Ojbc[40372:360247] log2:<NSObject: 0x600002ddc9f0>
2021-03-14 14:54:52.735926+0900 ARC_MemorySample_Ojbc[40372:360247] log3:(null)
2021-03-14 14:54:52.736001+0900 ARC_MemorySample_Ojbc[40372:360247] log4:(null)

__weak와 __unsafe_unretained가 다른점은?

 

__unsafe_unretained 예제

id __strong obj1 = [[NSObject alloc] init];
id __unsafe_unretained obj2 = obj1;
NSLog(@"log1:%@",obj1);
NSLog(@"log2:%@",obj2);
obj1 = nil;
NSLog(@"log3:%@",obj1);
NSLog(@"log4:%@",obj2);

__unsafe_unretained 결과

결과를 보면 알겠지만 __weak 경우엔 가리키고 있는 객체가 메모리에서 날라가면 nil set되지만 __unsafe_unretained 여전히 해당 객체가 있던 주소를 바라보고있다.

 

프로퍼티에서 사용할 경우

프로퍼티에서 해당 수식어를 사용하고싶다면 다음과 같이 매칭시켜 사용하면 된다.

프로퍼티 수식어 소유권 수식어
assign __unsafe_unretained
copy __strong(새로 복사된 객체가 할당된다.)
retain __strong
strong __strong
unsafe_unretained __unsafe_unretained
weak __weak

예제

 @property (weak) NSData *myData;
 @property (strong) NSDate *myData2;

 

autorelese

__autoreleasing? 굳이 쓸 필요 없다. 왜? 의미가 없기때문.. 아래예제를 참고

 

예제

@autoreleasepool { 
  id __strong obj1 = [[NSObject alloc] init]; 
  NSLog(@"log1:%@",obj1); 
  /* 오토릴리즈풀 안에 있기때문에 obj1은 오토릴리즈 풀에 등록이 된다. */ 
} 
/* @autoreleasepool 블록을 벗어났기때문에 풀에 등록이 되어있는 객체는 자동릴리즈된다. */

 

 

Swift

다음과 같은 수식어를 사용 할 수 있다.

 

strong

 - 강한참조, 해당 수식어를 가진 변수로 객체를 참조하게되면 retain count가 1증가한다.

weak

 - 약한참조, 해당 수식어를 가진 변수로 객체를 참조하여도 retain count가 증가하지않는다.

unowned

 - 약한참조, 해당 수식으를 가진 변수로 객체를 참조하여도 retain count 증가하지않는다.

 

예제

strong

 var myObj: NSObject? = NSObject()
 let myObjPtr: NSObject? = myObj
 print("log1:\(myObj)")
 print("log2:\(myObjPtr)")
 myObj = nil
 print("log3:\(myObj)")
 print("log4:\(myObjPtr)")

strong 결과

log1:Optional(<NSObject: 0x6000036481d0>)
log2:Optional(<NSObject: 0x6000036481d0>)
log3:nil
log4:Optional(<NSObject: 0x6000036481d0>)

weak

 var myObj: NSObject? = NSObject()
 weak var myObjPtr: NSObject? = myObj
 print("log1:\(myObj)")
 print("log2:\(myObjPtr)")
 myObj = nil
 print("log3:\(myObj)")
 print("log4:\(myObjPtr)")

weak 결과

log1:Optional(<NSObject: 0x6000036481d0>)
log2:Optional(<NSObject: 0x6000036481d0>)
log3:nil
log4:nil

weak VS unowned

Objective-C __weak __unsafe_unratained 차이와 정확히 동일하다. ( 참조)

 

weak를 사용해 순환참조 탈출하기

순환참조?

객체간의 포인터가 서로가 서로를 가르키게 되면 메모리 누수가 발생한다.

class ParentsClass {
    var child: ChildrenClass?
    init() {

    }

    func makeChild() {
        self.child = ChildrenClass(parentsClass: self)
    }
}

class ChildrenClass {
    var parentsClass: ParentsClass

    init(parentsClass: ParentsClass) {
        self.parentsClass = parentsClass
    }
}


class ViewController: UIViewController {
     func circulationReference() { //순환참조가 발생한다.
        let myClass = ParentsClass()
        myClass.makeChild()
    }
}

parentsClass가 강한참조로 child를 가지고있고, ChildrentClass역시 강한참조로 parantsClass를 가지고있다. 즉, 서로가 서로를 강한참조로 가르키고 있으니 retain count가 줄어 들 수 없다.

 

weak 수식어로 한곳의 포인터를 retain count 증가시키지 않게 만들어서 탈출하자 !

class ParentsClass { 
  var child: ChildrenClass? 
  
  init() {
  } 

  func makeChild() {
    self.child = ChildrenClass(parentsClass: self) 
  } 
} 

class ChildrenClass { 
  weak var parentsClass: ParentsClass? //weak 수식어를 사용함으로써 부모클래스의 retain count를 늘리지 않는다. 
  init(parentsClass: ParentsClass) { 
    self.parentsClass = parentsClass 
  } 
} 

class ViewController: UIViewController { 
  func circulationReference() { //순환참조가 발생하지않는다. 
    let myClass = ParentsClass() myClass.makeChild() 
  } 
}

샘플코드

 

 

HanweeeeLee/TestModules

이것저것 테스트하는 레포지토리입니다. Contribute to HanweeeeLee/TestModules development by creating an account on GitHub.

github.com

참조: iOS와 OS X의 메모리 관리와 멀티스레딩 기법 - 가즈키 사카모토, 도모히코 후루모토

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/09   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
글 보관함