[objective-c] 어떤 상황에서 ARC에서 __autoreleasing 소유권 한정자를 작성해야합니까?

퍼즐을 풀려고합니다.

__strongNSObject, NSString 등과 같은 모든 Objective-C 유지 가능 개체 포인터의 기본값입니다. 강력한 참조입니다. ARC -release는 범위의 끝에서 균형을 유지합니다 .

__unsafe_unretained옛날 방식과 같습니다. 유지 가능한 개체를 유지하지 않고 약한 포인터에 사용됩니다.

__weak__unsafe_unretained참조 된 객체가 할당 해제 되 자마자 포인터가 nil로 설정된다는 것을 의미하는 자동 영점 약한 참조라는 점을 제외하면 비슷 합니다. 이것은 댕글 링 포인터와 EXC_BAD_ACCESS 오류의 위험을 제거합니다.

그러나 정확히 무엇이 __autoreleasing좋은가요? 이 한정자를 사용해야 할 때에 대한 실용적인 예를 찾는 데 어려움을 겪고 있습니다. 나는 다음과 같은 포인터 포인터를 기대하는 함수와 메서드에만 해당한다고 생각합니다.

- (BOOL)save:(NSError**);

또는

NSError *error = nil;
[database save:&error];

ARC에서 다음과 같이 선언해야합니다.

- (BOOL)save:(NSError* __autoreleasing *);

그러나 이것은 너무 모호하며 이유 를 완전히 이해하고 싶습니다 . 내가 찾은 코드 스 니펫은 두 별 사이에 __autoreleasing을 배치하는데 이상하게 보입니다. 유형은 NSError**(NSError에 대한 포인터 포인터)이므로 왜 __autoreleasing별 사이에 배치 하고 단순히 NSError**?

또한 내가 의존해야하는 다른 상황이있을 수 있습니다 __autoreleasing.



답변

네가 옳아. 공식 문서에서 설명하는대로 :

__autoreleasing은 참조 (id *)로 전달되고 반환시 자동 해제되는 인수를 나타냅니다.

이 모든 것은 ARC 전환 가이드 에 잘 설명되어 있습니다.

NSError 예제에서 선언은 __strong암시 적으로 다음을 의미합니다 .

NSError * e = nil;

다음으로 변환됩니다.

NSError * __strong error = nil;

save메서드 를 호출 할 때 :

- ( BOOL )save: ( NSError * __autoreleasing * );

그런 다음 컴파일러는에 설정된 임시 변수를 만들어야합니다 __autoreleasing. 그래서:

NSError * error = nil;
[ database save: &error ];

다음으로 변환됩니다.

NSError * __strong error = nil;
NSError * __autoreleasing tmpError = error;
[ database save: &tmpError ];
error = tmpError;

오류 객체를로 __autoreleasing직접 선언하여이를 방지 할 수 있습니다.


답변

Macmade의 답변과 Proud Member의 댓글에 대한 후속 질문에 대한 후속 조치 (댓글로 게시했을 수도 있지만 최대 문자 수를 초과 함) :

다음은 __autoreleasing의 변수 한정자가 두 별 사이에 배치 된 이유입니다.

서문에 한정자를 사용하여 개체 포인터를 선언하는 올바른 구문은 다음과 같습니다.

NSError * __qualifier someError;

컴파일러는 이것을 용서할 것입니다 :

__qualifier NSError *someError;

그러나 그것은 정확하지 않습니다. Apple ARC 전환 가이드를 참조하십시오 ( “변수를 올바르게 장식해야합니다 …”로 시작하는 섹션 참조).

당면한 질문에 답하기 위해 : 메모리 주소를 가리키는 포인터는 객체에 대한 포인터가 아니라 기본 유형에 대한 포인터이기 때문에 이중 포인터는 ARC 메모리 관리 한정자를 가질 수 없습니다. 그러나 이중 포인터를 선언 할 때 ARC는 두 번째 포인터에 대한 메모리 관리 규칙이 무엇인지 알고 싶어합니다. 이것이 이중 포인터 변수가 다음과 같이 지정되는 이유입니다.

SomeClass * __qualifier *someVariable;

따라서 이중 NSError 포인터 인 메서드 인수의 경우 데이터 유형은 다음과 같이 선언됩니다.

- (BOOL)save:(NSError* __autoreleasing *)errorPointer;

영어로 “__autoreleasing NSError 객체 포인터에 대한 포인터”라고 말합니다.


답변

최종 ARC 사양은 말한다

__autoreleasing 객체의 경우 새 포인터가 유지되고 자동 해제되며 기본 의미 체계를 사용하여 lvalue에 저장됩니다.

예를 들어, 코드

NSError* __autoreleasing error = someError;

실제로 변환됩니다

NSError* error = [[someError retain] autorelease];

… 이것이 매개 변수가있을 때 작동하는 이유입니다 NSError* __autoreleasing * errorPointer. 호출 된 메소드는 오류를 할당 *errorPointer하고 위의 의미가 시작됩니다.

__autoreleasing다른 컨텍스트에서 ARC 객체를 자동 해제 풀에 강제로 사용할 수 있지만 ARC는 메서드 반환시 자동 해제 풀을 사용하는 것처럼 보이며 이미 자동으로 처리하기 때문에별로 유용하지 않습니다.


답변