Ios 计算中的BOOL属性使用valueForKey返回具有不正确值的NSNumber:

Ios 计算中的BOOL属性使用valueForKey返回具有不正确值的NSNumber:,ios,objective-c,kvc,Ios,Objective C,Kvc,我有一个简单的对象,它有一个NSNumber,用于存储一些标志。 我有一个Conience getter方法,它实际上可以: [self.flags integerValue] & SomeConstantFlag 暂时property@property只读,非原子,赋值BOOL someConstantFlag 当访问下面的bool值时,这可以很好地工作,比如 model.someConstantFlag 但是当我试着 id value = [model valueForKey:@

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

[self.flags integerValue] & SomeConstantFlag
暂时property@property只读,非原子,赋值BOOL someConstantFlag

当访问下面的bool值时,这可以很好地工作,比如

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对象,即使该属性具有标量类型

从重点矿井:

valueForKey:和setValue:forKey的默认实现: 提供对非对象数据的自动对象包装的支持 类型,包括标量和结构

Once valueForKey:已确定特定的访问器方法或 实例变量,用于为指定的 键,它检查返回类型或数据类型。如果值为 返回的不是对象,而是创建了NSNumber或NSValue对象 并在其位置返回

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

typedef signed char BOOL;
在OS X和32位iOS平台上。valueForKey返回的是一个NSNumber 包含结果的

signed char val = [self.flags integerValue] & SomeConstantFlag;
这可能在-128的范围内。。127

要确保仅获得是或否(即1或0),请将自定义getter编写为:

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

在64位IOS平台上,而不是在64位OS X上,BoOL被定义为C99μBoL,它是一个合适的布尔类型,只能取0或1的值。

< P>我认为您应该考虑以下问题。首先,integerValue返回NSInteger,这意味着如果您支持64位体系结构,它将返回int_64而不是int_32,这里的代码中还有什么

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

BOOL boolVal = [value boolValue];
    [self.flags integerValue] & SomeConstantFlag
如果flags为00010,somConstantFlags为00001,则执行以下操作&其中的值可能会达到您可能不期望的效果,因为您将获得等于0的值00000,或者如果它们为00011和00110,则您将获得等于2的00010。这就是为什么当你调用valueForKey时,你会得到2或4或其他取决于你的标志的东西: 更重要的是,在objective-C中,与0不同的一切都是肯定的

尝试重新考虑您的位逻辑:。请参见下面的示例

    enum 
    {
    kWhite   = 0,
    kBlue    = 1 << 0,
    kRed     = 1 << 1,
    kYellow  = 1 << 2,
    kBrown   = 1 << 3,
    };
    typedef char ColorType;
旗kWhite、kBlue、kRed和kYellow已经设置好


但是,kBrown尚未设置。

请尝试BOOL someBool=[model boolforky:@someconstanttflag];这可能是因为id类型?BOOL不是一个id。顺便说一句,2和4实际上都是,这不是事实,因为我正在使用一种处理XML=>创建的通用方法,我只发送一些属性及其相应的名称,以便我可以动态创建XML对象->到XML部分。所以我想在没有任何类型知识的情况下做这件事。问题出现在valueForKey:boxing->suggar代码boxing works ok@someBool.id是指向对象的指针。但是BOOL不是一个对象,我通过定义KVCCompilantBoolFromNumbera来克服这个问题?1:0我需要它,因为我只是从id对象本身创建了内部字符串值。问题是,正如前面提到的,简单装箱有效,valueForKey:not work->这是否意味着使用@someBool是另一种方式,valueForKey:@someBool知道类型并使用了uu nscfoolean??。从属性访问器返回值时强制转换为BOOL没有帮助@okipol:编译器将@someBool转换为[NSNumber numberWithBool:…],这就是它工作的原因。键值编码包装器不是那么聪明。-你试过我的建议吗?从声明为BOOL的方法返回一个0或1以外的值被大多数人认为是一个严重的错误,期望它最终会赶上你并咬你的屁股。正如它所做的那样。Martin的建议是解决您的问题的完美解决方案,您应该接受它,而不是坚持使用错误代码;。非常感谢!请查阅我不久前在使用define KVCCompilantBoolFromNumbera的主要问题后的评论?1:0我认为在manny getters和Acomplishs中,哪一个更易于重用,是不是?谢谢你描述糖盒和valueForKey之间的区别。@okipol:不客气a!=0完全等同于a?1:0,所以你可以选择你更喜欢的任何东西。-顺便说一句,您的问题不会发生在64位iOS上,我已经相应地更新了答案。anwser的Thx。但是我的逻辑是我想要的->在您的示例中,当我得到0时,我的属性表示未设置标志,当我得到2时,属性表示已设置特定标志。我使用标志将所有标志存储在SQLLiteDB->一个条目而不是nFl中
ag条目。我唯一的问题是,即使属性是BOOL,我也会得到一个如您所述的包装值,例如2,但我希望它是1或0,就像@will包装它一样。try[[model valueForKey:@someConstantFlag]boolValue]
ColorType pinkColor = kWhite | kRed;
if (pinkColor & (kWhite | kBlue | kRed | kYellow)) {
// any of the flags has been set
}