关于objective c:使用常量NSString作为NSUserDefaults的密钥

Using a constant NSString as the key for NSUserDefaults

我正在使用nsuserdefaults存储用户首选项。我记得在某个地方读到把键设置为常量是个好主意——我同意。以下代码是我目前拥有的代码:

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

我尝试将此更改为:

1
2
3
4
5
6
7
8
9
@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"。我希望我的代码没有编译器警告。如何修复此警告?


您应该使用:

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

而不是:

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

第一个是指向nsstring对象的常量指针,而第二个是指向常量nsstring对象的指针。

这是一个微妙的区别。出现编译器警告是因为setObject:forKey:声明如下:

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

它期望defaultName参数为NSString *类型。当你把一个指针传递给一个常量时,你给了它一些不同的东西。

更新:我想指出,如果这些常量只在单个文件中使用,那么它们应该定义为static。我这么说是因为我自己也遇到了这个问题:如果您不将它们声明为静态的,那么它们将存在于全局命名空间中,并且您将无法在另一个文件中使用具有相同名称的变量。有关更多信息,请参见Objective-C中的常量。举例说明,这是我目前使用的密钥,我只需要在一个.m文件中使用:

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


不要将const与objective-c对象一起使用,它们实际上不是为使用它而设计的。由于NSString对象(包括许多其他对象)的设计,默认情况下它们是不可变的,因此使它们const是无用的。

正如E.james所建议的,您可以使用NSString * const,它是指向NSString的常量指针。这与const NSString *略有不同(相当于NSString const *),后者是指向常量NSString的指针。使用NSString * const可防止您重新分配kPoly以指向新的NSString对象。


从其他类访问:

h

1
extern NSString * const PolygonNumberOfSidesPrefsKey;

m

1
NSString * const PolygonNumberOfSidesPrefsKey = @"PolygonNumberOfSidesPrefsKey"

仅限当前类内的访问:

m

1
static NSString * const kPolygonNumberOfSidesPrefsKey = @"PolygonNumberOfSidesPrefsKey"

我甚至建议把这个常数做得更具描述性。多边形边数的常数可以来自任何地方。作为一个建议,如何:

1
kDefaultsPolygonNumberOfSides;

相反。


关于这个问题的更多背景,有一篇关于维基百科的优秀文章用指针解释常量语法:http://en.wikipedia.org/wiki/const_correction pointers_and_references