__strong 및weak의 용도
배경.
iOS의 일상적인 개발에서 Block을 사용할 때 변수를
__weak
로 명시하여 순환 인용을 방지해야 한다.그런데 Block 내부에서 왜 다시 __strong
라고 성명했습니까?예제
Don't BB, show me the code.
프로그램원으로서 코드를 직접 올리는 것이 직관적이고 이해하기 쉽다.__weak
의 단점: @interface MyObject : NSObject
@end
@implementation MyObject
- (void)dealloc {
NSLog(@"MyObject dealloc");
}
@end
- (IBAction)buttonClickedWeak:(id)sender {
dispatch_async(dispatch_get_global_queue(0, 0), ^{
MyObject *obj = [[MyObject alloc] init];
__weak typeof(obj) weakObj = obj;
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSLog(@"GCD--sleepBefore obj:%@",weakObj);
sleep(3);
NSLog(@"GCD--sleepAfter obj:%@",weakObj);
});
sleep(1);
obj = nil;
NSLog(@" nil");
});
}
위에서 보여준 코드와 같이 시청자 여러분은 먼저 컨트롤러 출력의log가 어떤 것인지 분석하고 실제 결과와 같은지 확인할 수 있습니다.
다음은 실제 로그 출력입니다.
GCD--sleepBefore obj:
MyObject dealloc
nil
GCD--sleepAfter obj:(null)
여기서 우리는 첫 번째 병렬 대기열을 대기열 A, 두 번째 대기열 B라고 부른다. 분명히 대기열 A
sleep
이 있을 때 대기열 B는 이미 첫 번째 줄log까지 실행되었기 때문에 여기GCD--sleepBefore
의 로그는obj를 정상적으로 출력할 수 있다.따라서 대기열 A가 깨어나고 obj가 nil로 설정되어 풀려납니다.그래서 대기열 B가 3초 동안 깨어난 후GCD--sleepAfter
의log가 인쇄된obj는null
이다.__weak
과__strong
:- (IBAction)buttonclicked2:(id)sender {
dispatch_async(dispatch_get_global_queue(0, 0), ^{
MyObject *obj = [[MyObject alloc] init];
__weak typeof(obj) weakObj = obj;
dispatch_async(dispatch_get_global_queue(0, 0), ^{
__strong typeof(weakObj) strongObj = weakObj;
sleep(3);
NSLog(@"GCD--obj:%@",strongObj);
});
obj = nil;
NSLog(@" nil");
});
}
이번에 Block 내부에서obj를 강제로 인용했는데 대기열 B3s가 깨어난 후에 정확한 출력을 할 수 있을까요?
다음은 실제 로그 출력입니다.
MyObject dealloc
nil
GCD--obj:(null)
우리는 여전히 정확하게 출력할 수 없다는 것을 보았다. 이는 Block 내부 성명
__strong
은 대상이 Block 내부에서 강제로 인용되는 것을 보장할 수 있을 뿐이다. 즉, Block 실행 과정에서 방출되지 않기 때문이다. 그러나 Block을 실행할 때 대상이 방출되고 성명__strong
도 이 문제를 해결할 수 없기 때문이다.위에서 보여준 코드는 Block이 인용한 외부 변수weakObj
가 __weak
로 성명되었기 때문에 Block은obj를 강제로 인용하지 않기 때문에obj가 부여된값은nil로 바로 분석 함수를 촉발하여obj를 방출한다.그래서 Block 내부에 있는 __strong typeof(weakObj) strongObj = weakObj;
라는 문장을 집행할 때 실제로는 __strong typeof(weakObj) strongObj = nil;
에 해당한다__weak
과__strong
:- (IBAction)buttonclicked:(id)sender {
dispatch_async(dispatch_get_global_queue(0, 0), ^{
MyObject *obj = [[MyObject alloc] init];
__weak typeof(obj) weakObj = obj;
dispatch_async(dispatch_get_global_queue(0, 0), ^{
__strong typeof(weakObj) strongObj = weakObj;
sleep(3);
NSLog(@"GCD--obj:%@",strongObj);
});
sleep(1);
obj = nil;
NSLog(@" nil");
});
}
이번에 나는obj부치
nil
를 하기 전에 대기열 Asleep
를 1초 동안 대기열 B에 들어갈 때obj가 풀리지 않도록 했다. 대기열 B 3s가 깨어난 후에 정확한 출력을 할 수 있을까?다음은 실제 로그 출력입니다.
nil
GCD--obj:
MyObject dealloc
이번에 정상적으로 출력되었습니다. 이것은 obj부치
nil
이전에 대열 B의 __strong
성명을 실행했기 때문입니다. 이때 obj는 Block에 의해 강제로 인용됩니다. obj가 밖에서 부치nil
를 받은 후에 분석 함수를 촉발하지 않고 Block이 지나간 후에 촉발 분석을 합니다.결론
단순 사용
__weak
은 Block의 변수를 초래하여 실행 과정에서 방출되어 코드상의 논리적 오류를 초래할 수 있다.그래서 Block 내부에서 사용하는 것을 추천합니다__strong
.물론 Block 내부에서 사용__strong
도 Block 내부에서 실행하는 과정에서 대응하는 대상을 방출하지 않을 뿐 해당 대상이 Block에서 실행될 때 방출되지 않을 것을 보장할 수 없다.마지막으로 데모를 첨부하면 파트너가 코드를 다운로드하여 테스트를 할 수 있습니다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.