ARC में NSString को CFStringRef और CFStringRef को NSString?


87

मैं एआरसी में NSStringसे प्राप्त करने के सही तरीके को समझने की कोशिश कर रहा हूं CFStringRef? विपरीत दिशा जा रहा है, के लिए एक ही CFStringRefकरने के लिए NSStringएआरसी में?

मेमोरी लीक बनाए बिना ऐसा करने का सही तरीका क्या है?


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

क्या आप बता सकते हैं कि उन दो विकल्पों का उपयोग करने पर वास्तव में क्या हो रहा है?
झुमझम

काफी नहीं। मैं एआरसी का उपयोग नहीं करता, इसलिए मुझे पता है कि आपको यह करना है, लेकिन ऐसा क्यों

1
@GabrielePetronella ARC कोडिंग को आसान, कोड को छोटा और अधिक पठनीय बनाने और मानवीय त्रुटियों की संभावना को कम करने वाला था। इसलिए, अब retainआईएनजी और releaseवस्तुओं के संदर्भ संदर्भों का ध्यान रखने के बजाय , हमें अब "सुंदर" जैसे __bridge_transfer, __unsafe_unretainedऔर का उपयोग करना चाहिए __autoreleasing। किसी को भी इसके लिए समय नहीं मिला। (और गंभीरता से, यह पढ़ना मुश्किल है। मेरी राय में, यह स्मृति प्रबंधन की सुविधा नहीं देता है।)

1
@ H2CO3 जवाब के लिए धन्यवाद। मैं विशेष रूप से अंतिम वाक्य से असहमत हूं, लेकिन मैं आपकी बात का सम्मान करता हूं :)
गैब्रियल पेट्रोनेला

जवाबों:


177

आम तौर पर

NSString *yourFriendlyNSString = (__bridge NSString *)yourFriendlyCFString;

तथा

CFStringRef yourFriendlyCFString = (__bridge CFStringRef)yourFriendlyNSString;

अब, यदि आप जानना चाहते हैं कि __bridgeखोजशब्द क्यों है, तो आप Apple प्रलेखन का उल्लेख कर सकते हैं । वहाँ आप पाएंगे:

__bridge स्वामित्व के हस्तांतरण के साथ उद्देश्य-सी और कोर फाउंडेशन के बीच एक संकेतक स्थानांतरित करता है।

__bridge_retainedया CFBridgingRetainएक कोर फाउंडेशन सूचक के लिए एक उद्देश्य-सी सूचक डाली और आप के लिए स्वामित्व स्थानांतरित करता है। आप ऑब्जेक्ट के स्वामित्व को त्यागने के लिए CFRelease या संबंधित फ़ंक्शन को कॉल करने के लिए जिम्मेदार हैं।

__bridge_transferया CFBridgingReleaseऑब्जेक्टिव-सी के लिए नॉन-ऑब्जेक्टिव-सी पॉइंटर को मूव करता है और ओआरसी को ओनरशिप ट्रांसफर करता है। एआरसी वस्तु के स्वामित्व को त्यागने के लिए जिम्मेदार है।

जिसका अर्थ है कि उपरोक्त मामलों में आप स्वामित्व को बदले बिना ऑब्जेक्ट को कास्टिंग कर रहे हैं। इसका तात्पर्य यह है कि किसी भी स्थिति में आप स्ट्रिंग्स की मेमोरी को संभालने के प्रभारी नहीं होंगे।

ऐसा मामला भी हो सकता है जिसमें आप किसी कारण से स्वामित्व स्थानांतरित करना चाहते हैं।

उदाहरण के लिए निम्नलिखित स्निपेट पर विचार करें

- (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कास्टिंग करते समय स्वामित्व को स्थानांतरित करके बचाना चाहते हैं ।

- (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एक का उपयोग कर __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 → एनएसएसट्रिंग

// 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;

बहुत बहुत धन्यवाद, यह वास्तव में सहज नहीं है, लेकिन आपके लिए धन्यवाद, सबक सीखा
सल्फेन

@: थोड़ा सवाल। इसलिए यदि हम ARC का उपयोग करते हैं। कब NSString->CFString, हमें उपयोग करना चाहिए __bridge। लेकिन जब CFString->NSString, हमें उपयोग करना चाहिए__bride_transfer । ? और कोई भी साइड-इफ़ेक्ट, अगर हम CFReleaseतब उपयोग करते हैं जब हमें ज़रूरत नहीं होती है। धन्यवाद :)
hqt

@hqt, यदि आप 'आसान' तरीका चाहते हैं, तो हाँ जो आप कहते हैं वह सही है। इसके अलावा, एक अतिरिक्त CFReleaseआपके कार्यक्रम को यथोचित रूप से क्रैश कर सकता है, क्योंकि आप बेमेल बनाए रखने / रिलीज़ ऑपरेशन के साथ समाप्त हो जाएंगे, अंततः एक NULLपॉइंटर जारी करेंगे ।
गेब्रियल पेट्रोनेला
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.