วิธีการแปลง CFStringRef เป็น NSString?


169
NSString *aNSString;
CFStringRef aCFString;
aCFString = CFStringCreateWithCString(NULL, [aNSString UTF8String], NSUTF8StringEncoding);
aCFString = CFXMLCreateStringByUnescapingEntities(NULL, aCFString, NULL);

ฉันจะได้รับใหม่NSStringจากaCFString?

คำตอบ:


349

NSString และ CFStringRef เป็น "Toll ฟรีบริดจ์" ซึ่งหมายความว่าคุณสามารถพิมพ์ระหว่างพวกเขา

ตัวอย่างเช่น:

CFStringRef aCFString = (CFStringRef)aNSString;

ทำงานได้อย่างสมบูรณ์แบบและโปร่งใส ในทำนองเดียวกัน:

NSString *aNSString = (NSString *)aCFString;

ไวยากรณ์ก่อนหน้านี้สำหรับ MRC หากคุณใช้ ARC ไวยากรณ์การคัดเลือกนักแสดงใหม่จะเป็นดังนี้:

NSString *aNSString = (__bridge NSString *)aCFString;

ทำงานได้เช่นกัน สิ่งสำคัญที่ควรทราบคือ CoreFoundation มักจะส่งคืนวัตถุที่มีจำนวนการอ้างอิง +1 ซึ่งหมายความว่าพวกเขาจำเป็นต้องได้รับการปล่อยตัวออกมา (CF ทั้งหมด [ประเภท] สร้างฟังก์ชั่นการจัดรูปแบบทำเช่นนี้)

สิ่งที่ดีคือในโกโก้คุณสามารถใช้ระบบปล่อยอัตโนมัติหรือปล่อยเพื่อปล่อยให้เป็นอิสระ


88
หากคุณใช้ ARC แล้วไวยากรณ์การส่งใหม่สำหรับกรณีนี้คือ NSString * aNSString = (__bridge NSString *) aCFString
MikeG

6
ขอบคุณ MikeG ฉันต้องทำแบบเดียวกันกับการแปลงแบบย้อนกลับ: NSString * str = @ "abc"; CFStringRef cstrref = (__ สะพาน CFStringRef) str;
KomodoDave

2
@NilObject โปรดอัปเดตคำตอบของคุณเพื่อรวม ARC เพื่อให้ผู้ค้นหาไม่ต้องตรวจสอบความคิดเห็น ขอบคุณ
Dan Rosenstark

17

หากคุณกำลังใช้ ARC ในรุ่นล่าสุดของระบบปฏิบัติการ Mac OS X / วัตถุประสงค์ C ก็จริงง่าย:

NSString *happyString = (NSString *)CFBridgingRelease(sadString);

อย่างไรก็ตาม Xcode จะเตือนคุณอย่างมีความสุขเมื่อคุณพยายามโทรฟรีสะพาน CFString ไปที่ NSString และเสนอให้ห่อมันโดยอัตโนมัติใน CFBridgingRelease () ซึ่งคุณสามารถยอมรับและปล่อยให้มันใส่ wrapper ให้คุณโดยอัตโนมัติถ้าคุณคลิกตัวเลือก


3
ผมไม่แน่ใจ แต่ผมคิดว่า(__bridge NSString *)เป็นพอ: CFBridgingRelease()มีจุดในการเพิ่มเก็บนับด้วย
Cœur

12

พวกมันเทียบเท่ากันดังนั้นคุณสามารถส่ง CFStringRef ได้:

NSString *aNSString = (NSString*)aCFString;

สำหรับข้อมูลเพิ่มเติมโปรดดูที่ประเภทโทรฟรี Bridged


4

ที่จริงแล้วคุณไม่ควรใช้ Cocoa รักษาปล่อยและวางจำหน่ายอัตโนมัติในวัตถุหลักของมูลนิธิในทั่วไป หากคุณใช้ Garbage Collection (เฉพาะบน Mac OS X ในตอนนี้) การโทรออก, พักสาย, การยกเลิกอัตโนมัติจะไม่มีการใช้งานทั้งหมด ดังนั้นหน่วยความจำรั่ว

จาก Apple http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/GarbageCollection/Articles/gcCoreFoundation.html :

เป็นเรื่องสำคัญที่จะต้องเห็นคุณค่าของความไม่สมดุลระหว่าง Core Foundation และ Cocoa ซึ่งการคงไว้ซึ่งการปลดปล่อยและการหยุดอัตโนมัติโดยอัตโนมัตินั้นไม่มีความจำเป็น ตัวอย่างเช่นหากคุณมีความสมดุลของ CFC สร้าง ... ด้วยการเปิดตัวหรือเลิกอัตโนมัติคุณจะรั่วไหลของวัตถุในสภาพแวดล้อมที่เก็บขยะ:

NSString *myString = (NSString *)CFStringCreate...(...);
// do interesting things with myString...
[myString release]; // leaked in a garbage collected environment

ในทางกลับกันการใช้ CFRelease เพื่อปล่อยวัตถุที่คุณเก็บไว้ก่อนหน้านี้โดยใช้การเก็บรักษาจะส่งผลให้เกิดข้อผิดพลาดการอ้างอิงอันเดอร์โฟลว์


PS: ดูเหมือนจะไม่สามารถแสดงความคิดเห็นในคำตอบของปีเตอร์ Hosey - ขอโทษสำหรับการเพิ่มของฉันเองโดยไม่จำเป็น


3

ฉันจะเพิ่มที่ไม่เพียง แต่คุณสามารถไปจาก CFString ไปยัง NSString ด้วยการโยนประเภท แต่มันก็ทำงานในลักษณะอื่นเช่นกัน คุณสามารถวางCFStringCreateWithCStringข้อความซึ่งเป็นสิ่งที่น้อยกว่าที่คุณจะต้องปล่อยในภายหลัง (CF ใช้Createตำแหน่งที่ Cocoa ใช้allocดังนั้นไม่ว่าจะด้วยวิธีใดคุณจะต้องปล่อยมัน)

รหัสผลลัพธ์:

NSString *escapedString;
NSString *unescapedString = [(NSString *) CFXMLCreateStringByUnescapingEntities(NULL, (CFStringRef) escapedString, NULL) autorelease];

2

ฉันมีปัญหากับ ARC และจำนวนที่เก็บไว้ของ CFStrings การใช้คำตอบของ NilObjects ด้วยการปรับแต่งเล็กน้อยนั้นสมบูรณ์แบบสำหรับฉัน ฉันเพิ่งเพิ่มไว้เช่น

CFStringRef cfstringRef = (__bridge_retained  CFStringRef)aNsString;


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.