计算的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一个NSNumber
或NSValue
对象 ,并返回其位置。
你的方法的返回值是BOOL
,它被定义为
typedef signed char BOOL;
在OS X和32位iOS平台上。 那么valueForKey
返回的是包含结果的NSNumber
signed char val = [self.flags integerValue] & SomeConstantFlag;
并且可以在-128 … 127的范围内。
为了确保你只有YES
或NO
(又名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还没有设置。