การใช้ NSString คงที่เป็นกุญแจสำคัญสำหรับ NSUserDefaults


86

ฉันใช้ NSUSerDefaults เพื่อจัดเก็บค่ากำหนดของผู้ใช้ ฉันจำได้ว่าอ่านที่ไหนสักแห่งว่าการตั้งค่าคีย์เป็นค่าคงที่เป็นความคิดที่ดีและฉันก็เห็นด้วย รหัสต่อไปนี้คือสิ่งที่ฉันมีอยู่ในปัจจุบัน:

[[NSUserDefaults standardUserDefaults]
        setObject:[NSNumber numberWithInt:polygon.numberOfSides] 
           forKey:@"polygonNumberOfSides"];

ฉันลองเปลี่ยนสิ่งนี้เป็น:

@implementation Controller

NSString const *kPolygonNumberOfSides = @"polygonNumberOfSides";

-(void)savePolygonInfo {
    [[NSUserDefaults standardUserDefaults]
            setObject:[NSNumber numberWithInt:polygon.numberOfSides] 
               forKey:kPolygonNumberOfSides];
}

แม้ว่าจะได้ผล แต่ก็สร้าง " warning: passing argument 1 of 'objectForKey:' discards qualifiers from pointer target type" ฉันกระตือรือร้นที่จะรักษารหัสของฉันให้ปราศจากคำเตือนของคอมไพเลอร์ ฉันจะแก้ไขคำเตือนนี้ได้อย่างไร

คำตอบ:


208

คุณควรใช้:

NSString * const kPolygonNumberOfSides = @"..."; // const pointer

แทน:

NSString const * kPolygonNumberOfSides = @"..."; // pointer to const

ตัวแรกคือตัวชี้ค่าคงที่ไปยังวัตถุ NSString ในขณะที่ตัวที่สองเป็นตัวชี้ไปยังวัตถุ NSString ที่คงที่

มันเป็นความแตกต่างที่ลึกซึ้ง คำเตือนของคอมไพเลอร์เกิดขึ้นเนื่องจากsetObject:forKey:มีการประกาศดังนี้:

- (void)setObject:(id)value forKey:(NSString *)defaultName;

มันเป็นที่คาดหวังว่าอาร์กิวเมนต์เป็นชนิดdefaultName NSString *เมื่อคุณส่งตัวชี้ไปยังค่าคงที่แทนคุณจะให้สิ่งที่แตกต่างออกไป

อัปเดต:ฉันต้องการชี้ให้เห็นว่าค่าคงที่เหล่านี้ควรถูกกำหนดราวกับstaticว่าจะถูกใช้จากภายในไฟล์เดียวเท่านั้น ฉันพูดแบบนี้เพราะฉันเจอปัญหานี้ด้วยตัวเอง: ถ้าคุณไม่ประกาศว่ามันคงที่มันจะมีอยู่ในเนมสเปซส่วนกลางและคุณจะไม่สามารถใช้ตัวแปรที่มีชื่อเดียวกันในไฟล์อื่นได้ ดูค่าคงที่ใน Objective-Cสำหรับข้อมูลเพิ่มเติม เพื่ออธิบายโดยตัวอย่างนี่คือสิ่งที่ฉันใช้สำหรับคีย์ที่ฉันจำเป็นต้องใช้ใน.mไฟล์เดียวเท่านั้น:

static NSString * const kSomeLabel = @"...";

1
NSString * const fooใช้งานได้เนื่องจากNSStringไม่เปลี่ยนรูปและตัวชี้ไม่เปลี่ยนรูปจึงไม่สามารถเปลี่ยนแปลงได้ถูกต้อง? นอกจากนี้ฉันจำได้จาก C ++ ที่constเป็นนัยstatic(การเพิ่มประสิทธิภาพคอมไพเลอร์) ดังนั้นไม่จำเป็นต้องเรียกมันออกมา เป็นเช่นนั้นจริงหรือ?
Ternary

32

อย่าใช้constกับวัตถุ Objective-C พวกเขาไม่ได้ออกแบบมาเพื่อใช้งานจริงๆ NSStringวัตถุ (อื่น ๆ อีกมากมาย) นั้นไม่เปลี่ยนรูปโดยค่าเริ่มต้นแล้วตามการออกแบบดังนั้นการทำให้มันconstไร้ประโยชน์

ตามที่e. James แนะนำคุณสามารถใช้ an NSString * constซึ่งเป็นตัวชี้ค่าคงที่ไปยังNSStringไฟล์. นี้เป็นอย่างละเอียดแตกต่างจากconst NSString *(เทียบเท่าNSString const *) NSStringซึ่งเป็นตัวชี้ไปอย่างต่อเนื่อง การใช้เครื่องหมายNSString * constป้องกันไม่ให้คุณกำหนดใหม่kPolyให้ชี้ไปที่NSStringวัตถุใหม่


จุดดีเกี่ยวกับการใช้ const นั่นเป็นเหตุผลที่คลาส Objective-C จำนวนมากมีตัวแปรที่ "เปลี่ยนแปลงได้"

2
ฉันคิดว่านั่นconstหมายความว่าคุณไม่สามารถกำหนดใหม่ได้ ฉันเดาว่าฉันคิดผิด
Dan Rosenstark

18

สำหรับการเข้าถึงจากคลาสอื่น ๆ :

.h

extern NSString * const PolygonNumberOfSidesPrefsKey;

.m

NSString * const PolygonNumberOfSidesPrefsKey = @"PolygonNumberOfSides"

สำหรับการเข้าถึงภายในคลาสปัจจุบันเท่านั้น:

.m

static NSString * const kPolygonNumberOfSidesPrefsKey = @"PolygonNumberOfSides"

5

ฉันขอแนะนำให้ทำให้ค่าคงที่อธิบายได้มากขึ้น ค่าคงที่สำหรับจำนวนด้านของรูปหลายเหลี่ยมอาจมาจากที่ใดก็ได้ เป็นคำแนะนำวิธีการเกี่ยวกับ:

kDefaultsPolygonNumberOfSides;

แทน.

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