【问题标题】:Using a constant NSString as the key for NSUserDefaults使用常量 NSString 作为 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”。我热衷于让我的代码免受编译器警告的影响。如何解决此警告?

【问题讨论】:

    标签: objective-c cocoa default-value


    【解决方案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;
      

      改为。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-12-28
        • 1970-01-01
        • 2018-02-19
        • 1970-01-01
        • 2017-03-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多