计算的BOOL属性使用valueForKey返回带有incorect值的NSNumber:

我有一个简单的对象有一个NSNumber用于存储一些标志。 我有一个实际上确实的getter方法:

[self.flags integerValue] & SomeConstantFlag 

为属性@property (readonly, nonatomic, assign) BOOL someConstantFlag

当访问基础布尔值时,这工作正常

 model.someConstantFlag 

但是当我尝试

 id value = [model valueForKey:@"someConstantFlag"]; 

然后它返回一个错误的布尔表示,例如NSNumber的值为2,4等等。为什么当这个属性的声明是BOOL时会发生这种情况? 有一个“漂亮”的方法来克服这个问题?

另一方面包装工作正常:

 BOOL someBool = 42; NSNumber* numberVal = @(someBool); //The underlying is an __NSCFBoolean with the proper 0/1 val! 

valueForKey总是返回一个Objective-C对象,即使该属性具有标量types。

从文档 (重点是我的):

valueForKey:setValue:forKey:的默认实现提供对非对象数据types(标量和结构)的自动对象封装的支持。

一旦valueForKey:确定了用于为指定键提供值的特定访问方法或实例variables,它将检查返回types或数据types。 如果要返回的值不是一个对象,则为该值创build一个NSNumberNSValue对象 ,并返回其位置。

你的方法的返回值是BOOL ,它被定义为

 typedef signed char BOOL; 

在OS X和32位iOS平台上。 那么valueForKey返回的是包含结果的NSNumber

 signed char val = [self.flags integerValue] & SomeConstantFlag; 

并且可以在-128 … 127的范围内。

为了确保你只有YESNO (又名1或0),写下你的自定义getter:

 -(BOOL)someConstantFlag { return ([self.flags integerValue] & SomeConstantFlag) != 0; } 

备注:在64位iOS平台上(而不是在64位OS X上), BOOL被定义为C99 _Bool ,它是一个“正确的”布尔types,只能取值0或1。

 NSNumber *value = @([model objectForKey:@"someConstantFlag"]); BOOL boolVal = [value boolValue]; 

我想你应该考虑以下问题。 首先,integerValue返回NSInteger,这意味着如果你支持64位体系结构,它将返回int_64而不是int_32,这里的代码更多

  [self.flags integerValue] & SomeConstantFlag 

如果标志是00010和somConstantFlags是00001,那么这个会执行以下操作:&那些将会做你可能不期望的事情,因为你将得到00000的值等于0,或者如果它们是00011和00110,你将得到00010等于2。这就是为什么当你打电话给valueForKey你得到2或4或其他什么东西取决于你的旗帜:)什么是更多的Objective-C所有不同的,然后0是YES。

尝试重新考虑你的位逻辑:)。 请参阅以下示例

  enum { kWhite = 0, kBlue = 1 << 0, kRed = 1 << 1, kYellow = 1 << 2, kBrown = 1 << 3, }; typedef char ColorType; 

并在你的制定者检查以下内容

 ColorType pinkColor = kWhite | kRed; if (pinkColor & (kWhite | kBlue | kRed | kYellow)) { // any of the flags has been set } 

标志kWhite,kBlue,kRed和kYellow已被设置。

但是,kBrown还没有设置。