2014-04-24 1 views
0

저수준 API에서 CFDictionary 나 CFArray를 얻고 자동 참조로 계산 된 Objective-C 영역에 항목 중 하나만 유지하려고한다고 가정 해보십시오. 다음과 같음 :CFRelease'd 컬렉션에있는 항목에 대한 참조를 어떻게 연결해야합니까?

NSString* value = nil; 
CFDictionaryRef info = FrameworkCopySomeInfo(); 
value = (id)CFDictionaryGetValue(info, kFrameworkSomeKey); 
CFRelease(info); 
// BUG: presumably value is an invalid reference now! 

이처럼 가장 좋은 패턴은 무엇입니까? CFRelease을 호출하는 대신 __bridge_transfer 정보 사전을 사용해 보시기 바랍니다. 하지만 bridged casts documentation은 다음과 같이 말합니다 (강조 표시).

ARC는 값 [ 내 정보 사전]은 인 로컬 값에 대한 일반적인 최적화가 적용되는 의 전체 표현식 끝 부분에 있습니다.

나는

NSString* value = nil; 
NSDictionary* info = (__bridged_transfer id)FrameworkCopySomeInfo(); 
value = [info objectForKey:(__bridge id)kFrameworkSomeKey]; 
// …no further reference to `info`, but `value` continues to be used 

은 ... 아마도 컴파일러 내가 value 포인터를 얻을 직후 info 사전을 해제 할 수 ... 내 코드처럼 보이는 경우 걱정입니다. 가장 깨끗한 것은 무엇입니까 (가장 적은 캐스트, 혼란스럽지 만) 여기에도 여전히 정확한 패턴이 있습니까?

답변

0

나는이 올바른 생각, 또한 코드의 다른 독자들 내 의도를 명확하게 :

NSString* value = nil; 
CFDictionaryRef info = FrameworkCopySomeInfo(); 
value = [(__bridge id)CFDictionaryGetValue(info, kFrameworkSomeKey) copy]; 
CFRelease(info); 
NSLog(@"Still have the value: %@", value); 

행복한 다른 제안을하지만.

1

대신 컬렉션을 기초 유형으로 변환하는 것이 더 쉽습니다.

NSDictionary *info = CFBridgingRelease(FrameworkCopySomeInfo()); 
NSString *value = info[kFrameworkSomeKey]; 

관련 문서 현재 위치 : 그들이 브리지 때, 자동으로 유지됩니다, IIRC 브릿지, 그들은 범위 밖으로 갈 때 해제됩니다 https://developer.apple.com/library/mac/documentation/corefoundation/Conceptual/CFDesignConcepts/Articles/tollFreeBridgedTypes.html

+0

그러나 'value'에 대한 참조를 얻은 후에 바로 컴파일러가'info'를 릴리스 할 수 없습니까? 이것은 여전히 ​​그 값이 retain + autorelease를 얻는다 고 가정하는 것으로 보이는데, 이것은 [Get The Rule]과 모순이됩니다 (https://developer.apple.com/library/mac/documentation/corefoundation/Conceptual/CFMemoryMgmt/Concepts/Ownership). .html # // apple_ref/doc/uid/20001148-SW1) -'value'는'info'를 더 이상 사용하지 않으면 소유자가 없습니다. – natevw

+0

자동 참조 횟수는 자동으로 '값'을 유지합니다. – MaddTheSane

+0

@MaddTheSane 알았어, 좋을거야. 문서화 된 부분을 공유 할 수 있습니까? – natevw

1

항목. CFDictionaryGetValue()에 의해 반환 된 객체의 보유 수는 1이어야합니다 (보유하고있는 사전에서 1). 브릿지를 통과 한 후에는 보유 수 2가됩니다. CFRelease()을 사전에 호출하면 사전이 더 이상 보유하지 않기 때문에 오브젝트가 해제됩니다.

NSString* value = nil; 
CFDictionaryRef info = FrameworkCopySomeInfo(); 
value = (__bridge NSString*)CFDictionaryGetValue(info, kFrameworkSomeKey); 
CFRelease(info); 

두 번째 코드 예제는 완벽하게 유효하지만있는 NSString 형 값이없는 경우에는 kFrameworkSomeKey 캐스팅해야합니다 :

그래서 코드는 다음과 같을 것이다

value = [info objectForKey:(NSString*)kFrameworkSomeKey]; 

Apple이 자체적으로 CFStringRef을 ARC 안전하다고 표시하는 데 사용하는 일부 사전 처리기/컴파일러 속성이 있습니다.

value = [info objectForKey:(__bridge NSString*)kFrameworkSomeKey]; 

는 또한, 연타하다 정적 분석기는 당신의 친구입니다 : 나를 위해, 나는 내 사용자 지정 CFStringRef들에게이 일을 했어 당신이 버그를 진단하는 데 도움이 될 수 있습니다.

관련 문제