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하여 저장함
'iOS' 카테고리의 다른 글
저장된 대용량 이미지 파일을 resize하기 (0) | 2017.05.10 |
---|---|
HTML 태그를 AttributeString으로 변환하기 (0) | 2016.11.08 |
NSURLString 사용시 주의점 (0) | 2016.09.29 |
스토리보드에서 Segue호출 유의사항 (0) | 2016.09.29 |
UIActivityIndicatorView 사용시 주의점 (0) | 2016.09.23 |