ARC의 NSString에서 CFStringRef로 및 CFStringRef에서 NSString으로?


89

ARC NSString에서 를 얻는 올바른 방법을 이해하려고합니다 CFStringRef. 반대 방향으로가는 대한 동일 CFStringRefNSStringARC에?

메모리 누수를 일으키지 않고이를 수행하는 올바른 방법은 무엇입니까?


4
CFStringRef foo (__bridge CFStringRef)theNSString;NSString *bar = (__bridge NSString *)theCFString;

이 두 가지 옵션을 사용할 때 실제로 일어나는 일을 자세히 설명해 주시겠습니까?
zumzum

좀 빠지는. 저는 ARC를 사용하지 않습니다. 그래서 제가 아는 것은 여러분이 이것을해야한다는 것 뿐입니다.

1
@GabrielePetronella ARC는 코딩을 쉽게하고, 코드를 더 짧고, 더 읽기 쉽게 만들고, 인적 오류 가능성을 줄여야했습니다. 그래서, 지금 대신에 의해 참조 카운트 돌볼 필요없이 retain보내고 및 release객체를 -ing, 우리는 지금 같은 "아름다운"캐스트를 사용해야합니다 __bridge_transfer, __unsafe_unretained하고 __autoreleasing. 아무도 그럴 시간이 없습니다. (그리고 심각, 읽기가 더 어려워 제 생각에는, 그것은 전혀 메모리 관리를 용이하지 않았다..)

1
@ H2CO3 답변 주셔서 감사합니다. 난 강력 특히 마지막 문장으로, 동의,하지만 난 : 당신의 관점을 존중
가브리엘 Petronella

답변:


180

일반적으로

NSString *yourFriendlyNSString = (__bridge NSString *)yourFriendlyCFString;

CFStringRef yourFriendlyCFString = (__bridge CFStringRef)yourFriendlyNSString;

이제 __bridge키워드가있는 이유를 알고 싶다면 Apple 문서를 참조하십시오 . 다음을 찾을 수 있습니다.

__bridge 소유권 양도없이 Objective-C와 Core Foundation간에 포인터를 전송합니다.

__bridge_retained또는 CFBridgingRetainObjective-C 포인터를 Core Foundation 포인터로 캐스팅하고 소유권을 사용자에게 양도합니다. CFRelease 또는 관련 함수를 호출하여 개체의 소유권을 포기해야합니다.

__bridge_transfer또는 CFBridgingRelease비 Objective-C 포인터를 Objective-C로 이동하고 소유권을 ARC로 이전합니다. ARC는 객체의 소유권을 포기할 책임이 있습니다.

이는 위의 경우 소유권을 변경하지 않고 객체를 캐스팅한다는 것을 의미합니다. 이것은 두 경우 모두 문자열의 메모리를 처리 할 책임이 없음을 의미합니다.

어떤 이유로 든 소유권을 양도하려는 경우도있을 수 있습니다.

예를 들어 다음 스 니펫을 고려하십시오.

- (void)sayHi {
    CFStringRef str = CFStringCreateWithCString(NULL, "Hello World!", kCFStringEncodingMacRoman);

    NSString * aNSString = (__bridge NSString *)str;

    NSLog(@"%@", aNSString);

    CFRelease(str); //you have to release the string because you created it with a 'Create' CF function
}

CFRelease경우 캐스팅 할 때 소유권을 이전하여 a를 저장할 수 있습니다 .

- (void)sayHi {
    CFStringRef str = CFStringCreateWithCString(NULL, "Hello World!", kCFStringEncodingMacRoman);

    NSString * aNSString = (__bridge_transfer NSString *)str;
// or alternatively
    NSString * aNSString = (NSString *)CFBridgingRelease(str);

    NSLog(@"%@", aNSString);
}

의 소유권 str이 이전되었으므로 이제 ARC가 시작하여 메모리를 해제합니다.

반면에 캐스트 NSString *CFString사용하여 a를 __bridge_retained캐스트 할 수 있으므로 객체를 소유하고을 사용하여 명시 적으로 해제해야합니다 CFRelease.


그것을 마무리하기 위해 당신은 가질 수 있습니다

NSString → CFString

// Don't transfer ownership. You won't have to call `CFRelease`
CFStringRef str = (__bridge CFStringRef)string;

// Transfer ownership (i.e. get ARC out of the way). The object is now yours and you must call `CFRelease` when you're done with it
CFStringRef str = (__bridge_retained CFStringRef)string // you will have to call `CFRelease`

CFString → NSString

// Don't transfer ownership. ARC stays out of the way, and you must call `CFRelease` on `str` if appropriate (depending on how the `CFString` was created)
NSString *string = (__bridge NSString *)str;

// Transfer ownership to ARC. ARC kicks in and it's now in charge of releasing the string object. You won't have to explicitly call `CFRelease` on `str`
NSString *string = (__bridge_transfer NSString *)str;

대단히 감사합니다. 이것은 정말 직관적이지 않습니다.하지만 여러분 덕분에 교훈을 얻었습니다
Sulfkain

@ : 약간의 질문입니다. 그래서 우리가 ARC를 사용한다면. 때 NSString->CFString, 우리는 사용해야합니다 __bridge. 하지만 때 CFString->NSString, 우리는 사용해야합니다 __bride_transfer. ? 그리고 CFRelease우리가 필요하지 않을 때 사용 하면 부작용 이 있습니다. 감사합니다 :)
hqt

@hqt, 당신이 '쉬운'방법을 원한다면, 네 당신이 말하는 것이 맞습니다. 또한 불필요한 CFRelease유지 / 해제 작업으로 끝날 것이고 결국 NULL포인터를 해제하기 때문에 추가 프로그램이 합리적으로 프로그램을 충돌시켜야합니다 .
Gabriele Petronella
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.