ARC에서 항상 자신의 약한 참조를 블록에 전달하시겠습니까?
Objective-C에서의 블록 사용에 대해 조금 혼란스럽습니다.나는 현재 ARC를 사용하고 있고 내 앱에는 꽤 많은 블록이 있으며, 현재 항상 다음을 참조하고 있다.self
참조가 약한 대신.그것이 이러한 블록이 유지되는 원인일 수 있습니다.self
할당 해제되는 것을 막을 수 있을까요?문제는, 제가 항상 VIP를 사용해야 한다는 것입니다.weak
에 대한 언급.self
블록에?
-(void)handleNewerData:(NSArray *)arr
{
ProcessOperation *operation =
[[ProcessOperation alloc] initWithDataToProcess:arr
completion:^(NSMutableArray *rows) {
dispatch_async(dispatch_get_main_queue(), ^{
[self updateFeed:arr rows:rows];
});
}];
[dataProcessQueue addOperation:operation];
}
Process Operation.h
@interface ProcessOperation : NSOperation
{
NSMutableArray *dataArr;
NSMutableArray *rowHeightsArr;
void (^callback)(NSMutableArray *rows);
}
Process Operation.m
-(id)initWithDataToProcess:(NSArray *)data completion:(void (^)(NSMutableArray *rows))cb{
if(self =[super init]){
dataArr = [NSMutableArray arrayWithArray:data];
rowHeightsArr = [NSMutableArray new];
callback = cb;
}
return self;
}
- (void)main {
@autoreleasepool {
...
callback(rowHeightsArr);
}
}
집중하지 않는 것이 도움이 됩니다.strong
또는weak
논의의 일부입니다.대신 사이클 파트에 초점을 맞춥니다.
유지 사이클은 객체A가 객체B를 유지하고 객체B가 객체A를 유지할 때 발생하는 루프입니다.이 상황에서 어느 하나의 오브젝트가 해방된 경우:
- 오브젝트 B가 오브젝트에 대한 참조를 보유하고 있기 때문에 오브젝트 A는 할당 해제되지 않습니다.
- 그러나 오브젝트 A에 참조가 있는 한 오브젝트 B는 할당 해제되지 않습니다.
- 그러나 오브젝트 A는 오브젝트 B에 대한 참조가 있기 때문에 할당 해제되지 않습니다.
- 애드 인피니텀
따라서 이 두 개체는 모든 것이 제대로 작동한다면 할당 해제되어야 하지만 프로그램의 수명 동안 메모리에 남아 있게 됩니다.
즉, 유지 사이클이 우려됩니다.블록 자체만으로는 이러한 사이클이 발생하지 않습니다.이것은 문제가 되지 않습니다.예를 들어 다음과 같습니다.
[myArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop){
[self doSomethingWithObject:obj];
}];
블록이 유지되다self
,그렇지만self
블록은 유지되지 않습니다.둘 중 하나가 릴리스되면 사이클이 생성되지 않고 모든 것이 정상적으로 할당 해제됩니다.
문제가 되는 것은 다음과 같습니다.
//In the interface:
@property (strong) void(^myBlock)(id obj, NSUInteger idx, BOOL *stop);
//In the implementation:
[self setMyBlock:^(id obj, NSUInteger idx, BOOL *stop) {
[self doSomethingWithObj:obj];
}];
이제, 당신의 목적(self
)에는 명시적인 내용이 있습니다.strong
블록에 대한 참조.그리고 이 블록은 암묵적으로 강한 참조를 가지고 있습니다.self
이 주기는 주기이며, 이제 어느 개체도 제대로 할당 해제되지 않습니다.
왜냐하면, 이런 상황에서는self
정의상 이미 가 있다strong
블록에 대한 참조는 일반적으로 명시적으로 약한 참조를 함으로써 가장 쉽게 해결할 수 있습니다.self
사용할 블록:
__weak MyObject *weakSelf = self;
[self setMyBlock:^(id obj, NSUInteger idx, BOOL *stop) {
[weakSelf doSomethingWithObj:obj];
}];
단, 이것은 호출하는 블록을 처리할 때 따르는 기본 패턴은 아닙니다.self
! 이것은 자기와 블록 사이의 유지 사이클을 깨기 위해서만 사용해야 합니다.이 패턴을 모든 곳에 적용한다면 블록이 전달될 위험이 있습니다.self
을 사용하다
//SUSPICIOUS EXAMPLE:
__weak MyObject *weakSelf = self;
[[SomeOtherObject alloc] initWithCompletion:^{
//By the time this gets called, "weakSelf" might be nil because it's not retained!
[weakSelf doSomething];
}];
@jemmons에 전적으로 동의합니다.
그러나 이것이 셀프라고 불리는 블록을 처리할 때 따르는 기본 패턴은 아니어야 합니다.이것은 자기와 블록 사이의 유지 사이클을 깨는 데에만 사용해야 합니다.이 패턴을 모든 곳에 적용한다면, 자기 배정이 해제된 후에 실행되는 무언가에 블록을 전달하는 위험을 감수해야 합니다.
//SUSPICIOUS EXAMPLE: __weak MyObject *weakSelf = self; [[SomeOtherObject alloc] initWithCompletion:^{ //By the time this gets called, "weakSelf" might be nil because it's not retained! [weakSelf doSomething]; }];
하려면 , 이 강한 할 수 .weakSelf
록록: :
__weak MyObject *weakSelf = self;
[[SomeOtherObject alloc] initWithCompletion:^{
MyObject *strongSelf = weakSelf;
[strongSelf doSomething];
}];
항상 약한 참조를 사용할 필요는 없습니다.블록이 유지되지 않고 실행된 후 폐기된 경우 유지 사이클이 생성되지 않으므로 자신을 강하게 캡처할 수 있습니다.경우에 따라서는 블록이 완료될 때까지 블록이 자체 상태를 유지하여 너무 빨리 할당 해제되지 않도록 할 수도 있습니다.그러나 블록을 강하게 캡처하고 내부 캡처 셀프일 경우 유지 사이클이 생성됩니다.
Leo가 지적한 바와 같이, 질문에 추가한 코드는 강한 참조 주기(예: 유지 주기)를 시사하지 않습니다.강력한 참조 사이클을 일으킬 수 있는 동작 관련 문제 중 하나는 동작이 해제되지 않는 경우입니다.에 의해,되어 있지 않은 것이 행해지고 있는 는, 「」를 투고하지 는 릴리스 isFinished
뷰.조작이 해제되지 않으면 뷰 컨트롤러도 해제되지 않습니다.이나 중단점을 하는 것이 .NSLog
★★★★★★★★★★★★★★★★★★★★★★★★★.dealloc
이치노
당신이 말했다:
유지 사이클의 개념은 이해하지만 블록에서 무슨 일이 일어나는지 잘 모르기 때문에 조금 혼란스럽습니다.
블록에서 발생하는 유지 주기(강력한 참조 주기) 문제는 익숙한 유지 주기 문제와 동일합니다.블록은 블록 내에 표시되는 개체에 대한 강력한 참조를 유지하고 블록 자체가 해제될 때까지 이러한 강력한 참조를 해제하지 않습니다. references의 self
단순히 인 ''를 self
는 자신에은 블록이 이 「」가 해제될 까지) 되지 않습니다.NSOperation
서브클래스가 해방됩니다.
자세한 내용은 Programming with Objective-C: Working with Blocks 문서의 "Self Capting self(셀프 캡처 시 강력한 참조 주기 방지)" 섹션을 참조하십시오.
경우 되지 않은 하는 위치를 (「」를 합니다).NSOperation
할당 해제됩니다).로 '하다'를 들 수 .NSTimer
커스텀도 delegate
strong
하여 할 수 예를 다음과 같습니다.계측기를 사용하여 개체가 강력한 참조를 얻는 위치를 추적할 수 있습니다. §:
또는 Xcode 5의 경우:
일부 설명에서는 보유 사이클에 관한 조건을 무시합니다(강력한 관계의 원에서 오브젝트 그룹이 연결되어 있는 경우 그룹 외부에서 강력한 참조가 없어도 서로 존속합니다).상세한 것에 대하여는, 문서를 참조해 주세요.
블록 내부의 Self를 사용할 수 있는 방법은 다음과 같습니다.
//블록의 개요
NSString *returnedText= checkIfOutsideMethodIsCalled(self);
NSString* (^checkIfOutsideMethodIsCalled)(*)=^NSString*(id obj)
{
[obj MethodNameYouWantToCall]; // this is how it will call the object
return @"Called";
};
언급URL : https://stackoverflow.com/questions/20030873/always-pass-weak-reference-of-self-into-block-in-arc
'source' 카테고리의 다른 글
Swift: 객체 배열을 알파벳 순으로 정렬합니다. (0) | 2023.04.09 |
---|---|
이름 또는 유형별로 WPF 컨트롤을 찾으려면 어떻게 해야 합니까? (0) | 2023.04.09 |
IF 문: 조건이 false일 경우 셀을 공백으로 두는 방법("does not function") (0) | 2023.04.09 |
NSMutable Array를 셔플하는 가장 좋은 방법은 무엇입니까? (0) | 2023.04.09 |
Swift Language 추상 함수 (0) | 2023.04.09 |