objective C에서 block을 파라메터를 넘길 때 해당 block을 property에 저장해서 필요할 때 호출하기 위해 copy를 하게 된다.

copy를 하게 되면 블럭안에 사용되는 객체의 레퍼런스 카운트가 증가하게 된다.


@interface TestDummy 
@property (nonatomic, copy) void(^testBlock);
@end

....

[self.dummy testBlock:^ {

      [self complete];

}]; // dummy 인스턴스 내부에 block을 저장하기 위해 block을 copy하여 저장함


이 때 블럭안에 사용되는 self도 dummy객체의 copy 프로퍼티에 의해 참조하게 되여 순환참조 상황이 발생하게 된다.

이 순환참조를 방지하기 위해 weak 레퍼런스를 사용하여 self자체의 레퍼런스카운트 증가를 방지하게 된다



@interface TestDummy 
@property (nonatomic, copy) void(^testBlock);
@end

....

__weak __typeof(self)weakSelf = self;

[self.dummy testBlock:^ {

__strong __typeof(weakSelf)self = weakSelf;

      [self complete];

}]; // dummy 인스턴스 내부에 block을 저장하기 위해 block을 copy하여 저장함


하지만 위 케이스에서도 예외사항이 발생되는데 만약 호출한 클래스의 멤버변수를 block안에 실행하게 되면 다시 순환 참조가 발생하게 된다.


@interface TestDummy 
@property (nonatomic, copy) void(^testBlock);
@end

....

@interface TestOwner
@property (nonatomic, strong) NSArray *list;
@end

....

__weak __typeof(self)weakSelf = self;

[self.dummy testBlock:^ {

__strong __typeof(weakSelf)self = weakSelf;


      [self complete];

     [ _list removeAllObject]; // <-------- self를 사용안하고 멤버변수에 바로 접근하여 순한참조 발생함

}]; // dummy 인스턴스 내부에 block을 저장하기 위해 block을 copy하여 저장함


위 경우 잠재적인 메모리릭 상황이 발생하기 때문에 block안에 멤버변수를 사용하는 것은 주의가 필요하다



@interface TestDummy 
@property (nonatomic, copy) void(^testBlock);
@end

....

@interface TestOwner
@property (nonatomic, strong) NSArray *list;
@end

....

__weak __typeof(self)weakSelf = self;

[self.dummy testBlock:^ {

__strong __typeof(weakSelf)self = weakSelf;


      [self complete];

     [ self.list removeAllObject]; // <-------- 멤버변수에서 프로퍼티 접근으로 변경

}]; // dummy 인스턴스 내부에 block을 저장하기 위해 block을 copy하여 저장함



+ Recent posts