使用常量NSString作为NSUserDefaults的键

87

我正在使用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"。我想保持我的代码没有编译器警告。该如何解决这个警告?

4个回答

212

你应该使用:

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。我之所以这样说是因为我自己遇到过这个问题:如果你没有将它们声明为 static,那么它们将存在于全局命名空间中,你就不能在另一个文件中使用同名的变量。有关更多信息,请参见Objective-C 中的常量。举个例子来解释,这是我目前在一个 .m 文件中仅需要使用一次的键所使用的代码:
static NSString * const kSomeLabel = @"...";

1
NSString * const foo 之所以有效,是因为 NSString 是不可更改的,并且指针是不可更改的,因此它永远不会改变,对吧?另外,我记得在 C++ 中,const 隐式地是 static(编译器优化),所以不需要显式声明。这在这里也是正确的吗? - Ternary

33
不要在Objective-C对象中使用const,它们并没有真正设计为使用它。由于其设计的特性,NSString等对象已经默认为不可变对象,因此将它们设置为const是无用的。
正如e.James建议的那样,您可以使用NSString * const,这是一个指向NSString的常量指针。这与const NSString *(等同于NSString const *)略有不同,后者是指向常量NSString的指针。使用NSString * const可以防止您重新对kPoly进行赋值以指向新的NSString对象。

使用const的好处很明显。这就是为什么许多Objective-C类都有“Mutable”变体的原因。 - e.James
3
我原来以为 const 的意思是你不能重新赋值,现在看来我错了。 - Dan Rosenstark
根据你的第二段,我认为你应该修改第一段。无法重新分配标识符是一个有效的用途,并且与对象本身的可变性没有什么关系。如果你将NSString声明为NSString* const foo = @"bar",然后稍后尝试重新分配它,你会得到错误Cannot assign to variable 'foo'...这正是我在声明某些内容为const时所希望的。 - vegashacker

18

对于其他类的访问:

.h

extern NSString * const PolygonNumberOfSidesPrefsKey;

.m

:这是一个简短的HTML代码片段,它表示以 ".m" 结尾的文件或文件类型。
NSString * const PolygonNumberOfSidesPrefsKey = @"PolygonNumberOfSides"
仅供当前类内部访问:

.m

static NSString * const kPolygonNumberOfSidesPrefsKey = @"PolygonNumberOfSides"

5

我建议将常量的描述性更加具体。一个表示多边形边数的常量可能来自于任何地方。作为一个建议,可以这样:

kDefaultsPolygonNumberOfSides;

改为使用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接