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”。我热衷于让我的代码不受编译器警告的影响。我该如何解决这个警告?

4

4 回答 4

211

你应该使用:

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

代替:

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

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

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

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

它期望defaultName参数是 type NSString *。当你传入一个指向常量的指针时,你给了它一些不同的东西。

更新:我想指出,这些常量应该被定义为static好像它们只会在单个文件中使用一样。我这样说是因为我自己也遇到过这个问题:如果你不将它们声明为静态,那么它们将存在于全局命名空间中,你将无法在另一个文件中使用同名的变量。有关详细信息,请参阅Objective-C 中的常量。举例来说,这是我目前用于只需要在一个.m文件中使用的键的内容:

static NSString * const kSomeLabel = @"...";
于 2009-04-15T21:31:18.160 回答
32

不要const与 Objective-C 对象一起使用,它们并不是真正设计用来使用它的。 NSString默认情况下,对象(以及许多其他对象)由于其设计而已经是不可变的,因此制作它们const是无用的。

正如e.James 建议的那样,您可以使用 an NSString * const,它是指向 an 的常量指针NSStringconst NSString *这与 a (等价于)略有不同NSString const *,后者是一个指向常量的指针NSString。使用 aNSString * const可以防止您重新分配kPoly以指向新NSString对象。

于 2009-04-15T21:37:05.683 回答
18

对于其他类的访问:

。H

extern NSString * const PolygonNumberOfSidesPrefsKey;

.m

NSString * const PolygonNumberOfSidesPrefsKey = @"PolygonNumberOfSides"

仅在当前类内访问:

.m

static NSString * const kPolygonNumberOfSidesPrefsKey = @"PolygonNumberOfSides"
于 2013-11-10T22:00:47.523 回答
5

我建议甚至使常数更具描述性。多边形边数的常数可以来自任何地方。作为一个建议,怎么样:

kDefaultsPolygonNumberOfSides;

反而。

于 2009-04-18T12:14:14.383 回答