使用常量 NSString 作为 NSUserDefault 的键

我使用 NSUSerDefault 来存储用户首选项。我记得在什么地方读到过,把键设置为常量是个好主意——我也同意。下面是我目前的代码:

[[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”。我希望我的代码不受编译器警告的影响。我如何修正这个警告?

50559 次浏览

You should use:

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

instead of:

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

The first is a constant pointer to an NSString object, while the second is a pointer to a constant NSString object.

It is a subtle difference. The compiler warning happens because setObject:forKey: is declared as follows:

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

It is expecting the defaultName argument to be of type NSString *. When you instead pass in a pointer to a constant, you've given it something different.

Update: I want to point out that these constants should be defined as static if they are only going to be used from within a single file. I say this because I have run across this problem myself: if you do not declare them as static, then they will exist in the global namespace, and you will not be able to use a variable with the same the same name in another file. see Constants in Objective-C for more information. To explain by example, this is what I currently use for keys that I only need to use in one .m file:

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

Don't use const with Objective-C objects, they weren't really designed to use it. NSString objects (among many others) are already immutable by default by virtue of their design, so making them const is useless.

As e.James suggested, you can use an NSString * const, which is a constant pointer to an NSString. This is subtly different from a const NSString * (equivalent to NSString const *), which is a pointer to a constant NSString. Using a NSString * const prevents you from reassigning kPoly to point to a new NSString object.

I would suggest even making the constant more descriptive. A constant for the number of sides of a polygon could come from anywhere. As a suggestion, how about:

kDefaultsPolygonNumberOfSides;

instead.

For access from other classes:

.h

extern NSString * const PolygonNumberOfSidesPrefsKey;

.m

NSString * const PolygonNumberOfSidesPrefsKey = @"PolygonNumberOfSides"

For access only inside current class:

.m

static NSString * const kPolygonNumberOfSidesPrefsKey = @"PolygonNumberOfSides"