使用常量 NSString 作为 NSUserDefaults 的键
Posted
技术标签:
【中文标题】使用常量 NSString 作为 NSUserDefaults 的键【英文标题】:Using a constant NSString as the key for NSUserDefaults 【发布时间】:2010-10-19 17:15:58 【问题描述】:我正在使用 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
”。我热衷于让我的代码免受编译器警告的影响。如何解决此警告?
【问题讨论】:
【参考方案1】:对于其他类的访问:
.h
extern NSString * const PolygonNumberOfSidesPrefsKey;
.m
NSString * const PolygonNumberOfSidesPrefsKey = @"PolygonNumberOfSides"
仅在当前类内访问:
.m
static NSString * const kPolygonNumberOfSidesPrefsKey = @"PolygonNumberOfSides"
【讨论】:
【参考方案2】:你应该使用:
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
。我这样说是因为我自己也遇到过这个问题:如果你不将它们声明为静态,那么它们将存在于全局命名空间中,你将无法在另一个文件中使用同名的变量。请参阅Constants in Objective-C 了解更多信息。举例说明,这是我目前只需要在一个 .m
文件中使用的密钥:
static NSString * const kSomeLabel = @"...";
【讨论】:
NSString * const foo
之所以有效,是因为NSString
是不可变的,并且指针是不可变的,所以它永远不会改变对吗?另外,我从 C++ 中回忆起 const
隐含为 static
(编译器优化),因此无需调用它。这里也是这样吗?【参考方案3】:
不要将const
与Objective-C 对象一起使用,它们并不是真正设计用于使用它的。 NSString
对象(以及许多其他对象)在设计上已经默认是不可变的,因此将它们设置为 const
是没有用的。
作为e.James suggested,您可以使用NSString * const
,它是一个指向NSString
的常量指针。这与const NSString *
(相当于NSString const *
)略有不同,后者是一个指向常量NSString
的指针。使用 NSString * const
可以防止您重新分配 kPoly
以指向新的 NSString
对象。
【讨论】:
关于使用 const 的好处。这就是为什么很多 Objective-C 类都有“可变”变体的原因。 我认为const
也意味着你不能重新分配它。我想我错了。
鉴于你的第二段,我认为你应该修改你的第一段。无法重新分配标识符是一种有效的用途,并且与对象本身的可变性没有任何关系。如果您将 NSString 声明为 NSString* const foo = @"bar"
,然后尝试重新分配它,您将收到错误 Cannot assign to variable 'foo'...
,这正是我在声明 const 时所希望的。【参考方案4】:
我建议甚至使常数更具描述性。多边形边数的常数可以来自任何地方。作为一个建议,如何:
kDefaultsPolygonNumberOfSides;
改为。
【讨论】:
以上是关于使用常量 NSString 作为 NSUserDefaults 的键的主要内容,如果未能解决你的问题,请参考以下文章
Objective-C JSON 到 TableView 非常慢
使用 reverseGeocodeLocation 将用户的状态作为 NSString 返回