2012-12-28 2 views
31

약간 혼란 스럽네요. 내가 읽은 모든 곳에서 ARC를 사용할 때 여전히 핵심 기초 객체를 릴리스해야한다고 제안합니다. ARC는이를 관리하지 않습니다. 그러나, 나는 CFRelease을 사용하는 일부 CF 메서드/개체를 사용하는 메서드를 가지고 있지만 그 다음에 응용 프로그램이 중단됩니다. 내 CFRelease의 주석을 제거하면 문제가 해결되지만 메모리 누수가 있다고 가정합니다.ARC 및 CF 릴리즈?

누군가이 자료를 공개해야하는지, 어떤 자료를 필요로하는지 또는이 코드에 문제가 있는지 설명해주세요.

+ (NSString *) fileExtensionForMimeType:(NSString *)type 
{ 
    CFStringRef mimeType = (__bridge CFStringRef)type; 
    CFStringRef uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, mimeType, NULL); 
    CFStringRef extension = UTTypeCopyPreferredTagWithClass(uti, kUTTagClassFilenameExtension); 

    NSString *ext = (__bridge NSString *)extension; 

    // CFRelease(mimeType); 
    // CFRelease(uti); 
    // CFRelease(extension); 

    return ext; 
} 

세 주석 CFRelease 호출은 언급 한 바와 같이 문제를 해결하지만, 나는 그것이 잘못 알고있다. 나는 무엇을해야만 하는가?

+0

. 주석 처리를 해제하면 – Raptor

+1

내가 주석 처리를 취소하면 EXC_BAD_ACCESS 예외로 인해 응용 프로그램이 중단됩니다. 악기에서 추적을하면이 메소드를 가리키고 해당 라인에 주석을 달아 수정합니다 – PaReeOhNos

+2

mimeType의 참조 횟수를 늘리지 않으므로 uti 및 extension 만 릴리스해야 mimeType은 릴리스하지 마십시오. 당신은 단순히 그것을 유형 캐스팅합니다.CFRelease에 마지막으로 주석을 달고 어떤 일이 발생했는지 알려주세요. –

답변

34

자신이 소유하지 않았기 때문에 mimeType을 출시 할 수 없습니다. __bridge 시전으로 소유권을 이전하지 않았습니다.

작성한 이후 uti을 릴리스해야합니다.

도 만들었으므로 extension을 릴리스해야하지만 이는 ext에서 문제를 일으킬 수 있습니다. 대신 소유권을 ext으로 전송하세요.

나는 다음과 같은 제안하십시오 : CFRelease (UTI)과 CFRelease을 :

+ (NSString *) fileExtensionForMimeType:(NSString *)type { 
    CFStringRef mimeType = (__bridge CFStringRef)type; 
    CFStringRef uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, mimeType, NULL); 
    CFStringRef extension = UTTypeCopyPreferredTagWithClass(uti, kUTTagClassFilenameExtension); 

    NSString *ext = (__bridge_transfer NSString *)extension; 

    // CFRelease(mimeType); // not owned 
    if (uti) CFRelease(uti); 
    // CFRelease(extension); // ownership was transferred 

    return ext; 
} 
+5

+1 WWDC 2012에서 애플은'__bridge_transfer'보다는'CFBridgingRelease'를 제안했습니다. 또한 소유권을'__bridge_transfer'에서 ARC로'ext'로 옮겼으므로'CFRelease (extension)'가 필요하다는 것을 확신 할 수 있습니다. – Rob

+0

CFBridgingRelease가 __bridge_transfer와 같다고 생각했습니다. 문서에서 차이가 있음을 나타내지 않습니다. 관계없이, 나는 당신이 전송으로 인해 연장을 공개하지 않는 것이 옳다고 생각합니다. 내 대답을 업데이트 할게. 감사. – rmaddy

+0

그래,'CFBridgingRelease'의 정의를 보면, 그냥'__bridge_transfer'하지만, 애플이 새로운 구문을 추천했다고 가정합니다. 가독성을위한 것이거나'CFBridgingRelease'에 대한 미래의 포부가 있는지 여부는 알 수 없습니다. 어느 쪽이든 괜찮습니다. – Rob

0

일반적으로, 나는 첫 번째 CFRelease (mimeType를) 라인을 언급하려고하고 다음 두 줄의 주석을 해제해야한다고 생각 (신장). NSString을 입력하기 위해 유료 브리지를 캐스팅하고 ARC가이 릴리스를 처리합니다. 하지만 uti와 확장 기능은 CFString으로 생성/복사됩니다. ARC는 이들을 처리하는 방법을 알지 못합니다 (ARC가 NSObject의 컴파일러 기능이라는 것을 기억하십시오), 그래서 CF를 릴리즈해야합니다.

+1

그리고 @rmaddy가 말했듯이, 확장에서 __bridge_transfer를 추가하여 CF에서 NSObject로 유지 카운트 외도를 전송합니다. – onevcat

14

핵심 기초 개체 및 ARC에 대한 새로운 지침을 설명하는 WWDC 2012 - Modern Objective-C을 확인하십시오. 그 비디오에 대해 37:35 정도입니다. 간단히 말해, 코어 파운데이션은 이름에 Copy 또는 Create으로 기능하여 소유권을 앱으로 이전 한 개체를 만들고 앱이 해당 앱을 릴리스해야합니다. 소유권 이름으로 Copy 또는 Create와 코어 재단 방법을 통해 전송 된 경우

어쨌든, 당신은 CFRelease와 수동 중 출시 당신은 쉽게, 당신은 ARC에 소유권을 이전 할 수 있습니다, 그것을 함께 할, 또는있는 때 그것을 처리하게하십시오. 역사적으로 소유권을 ARC로 이전하기 위해 __bridge_transfer을 사용했지만 이제는 CFBridgingRelease을 권장합니다 (후자는 이전 매크로의 매크로 임). 그리고 분명히 이름에 Copy 또는 Create이있는 함수 이외의 다른 메커니즘을 통해 검색 한 Core Foundation 객체가있는 경우 CFRelease도 아니며 소유권을 ARC로 넘겨서도 안됩니다. 그림의 방법으로

,이 방법은 당신이 원하는 것을 달성 :

3 명령을 주석으로 무슨 문제
+ (NSString *) fileExtensionForMimeType:(NSString *)type { 

    NSString *uti = CFBridgingRelease(UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, 
                      (__bridge CFStringRef)type, 
                      NULL)); 

    return CFBridgingRelease(UTTypeCopyPreferredTagWithClass((__bridge CFStringRef)uti, 
                  kUTTagClassFilenameExtension)); 
}