使用常量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”。我渴望使我的代码不受编译器警告的影响。如何解决此警告?

Answers:


207

您应该使用:

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(编译器优化),因此无需大声疾呼。这也是真的吗?
三元

32

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

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


关于使用const的好处。这就是为什么许多Objective-C类具有“可变”变体的原因。
e.James

2
我认为这const也意味着您无法重新分配它。我想我错了。
Dan Rosenstark 2011年

18

对于其他类别的访问:

。H

extern NSString * const PolygonNumberOfSidesPrefsKey;

.m

NSString * const PolygonNumberOfSidesPrefsKey = @"PolygonNumberOfSides"

仅在当前类内部访问:

.m

static NSString * const kPolygonNumberOfSidesPrefsKey = @"PolygonNumberOfSides"

5

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

kDefaultsPolygonNumberOfSides;

代替。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.