我正在使用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
”。我渴望使我的代码不受编译器警告的影响。如何解决此警告?
您应使用:
NSString * const kPolygonNumberOfSides = @"..."; // const pointer
而不是:
NSString const * kPolygonNumberOfSides = @"..."; // pointer to const
第一个是指向NSString对象的常量指针,而第二个是指向恒定NSString对象的指针。
这是微妙的区别。发生编译器警告是因为setObject:forKey:
声明如下:
- (void)setObject:(id)value forKey:(NSString *)defaultName;
期望defaultName
参数为NSString *
类型。相反,当您传递指向常量的指针时,您给了它不同的东西。
[Update:我想指出,如果仅在单个文件中使用这些常量,则应将其定义为static
。我之所以这样说,是因为我自己遇到了这个问题:如果您不将它们声明为静态,则它们将存在于全局名称空间中,并且您将无法在另一个文件中使用具有相同名称的变量。有关更多信息,请参见Constants in Objective-C。为了举例说明,这是我目前用于只需要在一个.m
文件中使用的键的内容:
static NSString * const kSomeLabel = @"...";
不要将const
与Objective-C对象一起使用,它们并不是真正为使用它而设计的。默认情况下,NSString
对象(还有许多其他对象)由于其设计已经是不可变的,因此使它们成为const
是没有用的。
作为e.James suggested,您可以使用NSString * const
,它是指向NSString
的常量指针。这与const NSString *
(等效于NSString const *
)略有不同,后者是指向常量NSString
的指针。使用NSString * const
可以防止您重新分配kPoly
指向新的NSString
对象。
用于从其他类进行访问:
。h
extern NSString * const PolygonNumberOfSidesPrefsKey;
。m
NSString * const PolygonNumberOfSidesPrefsKey = @"PolygonNumberOfSides"
仅用于在当前类内部访问:
。m
static NSString * const kPolygonNumberOfSidesPrefsKey = @"PolygonNumberOfSides"
我建议甚至使常数更具描述性。多边形边数的常数可以来自任何地方。作为建议,如何:
kDefaultsPolygonNumberOfSides;
代替。
有关此问题的其他背景,Wikipedia上有一篇很好的文章,解释了带有指针的常量语法:http://en.wikipedia.org/wiki/Const_correctness#Pointers_and_references