iPhone:将布尔值保存到Core Data

53

我将我的一个核心数据属性设置为布尔类型。现在,我需要设置它,但 XCode 告诉我可能无法响应 setUseGPS 方法。

[ride setUseGPS: useGPS.on];

在Core Data中设置布尔值的方法是什么?我所有的其他属性都是这样设置的,它们运行得非常好。所以,不确定为什么不能像这样设置布尔值。

4个回答

134

Core Data没有布尔类型(实际上它有,但是它是NSNumber类型)。

因此,要设置相当于useGPS = YES的值。

[entity setUseGPS:[NSNumber numberWithBool:YES]];

另一种方法是:

BOOL isGPSOn = [[entity useGPS] boolValue];

更新: 正如SKG所指出的,使用Objective-C中的字面量(literals)你现在可以以一种更简单的方式来实现它:

[entity setUseGPS:@YES];

BOOL isGPSOn = entity.useGPS.boolValue;

9
你也可以像这样设置数值:object.isGPSOn = @YES; - abc123
显然,在核心数据编辑器中创建新属性时,我实际上可以在下拉菜单中看到布尔类型。这是怎么回事? - zulkarnain shah

18

对于已有的回答,作为另一种替代方法,你可以简单地将托管对象接口定义中的NSNumber *更改为BOOL,例如:

@property (nonatomic) BOOL useGPS;   // Notice that the 'retain' is also removed as we're now dealing with a scalar rather than an NSObject

这里讨论了各种替代方法(链接),但是Chris Hanson的回答对我来说最有启发性,特别是:

如果您有一个数字属性(包括布尔属性),需要它是必需的,您可以将其键入为标量,Core Data会做正确的事情:

@property (nonatomic) BOOL isDone;

即使该属性是可选的,它仍然有效-它将“不出现”与“false”混合在一起。

对于更加符合Cocoa的实现方法:

另外一个您可能想做的事情是将属性命名为“done”,并将getter指定为“isDone”。这是通常的Cocoa命名约定:

@property (nonatomic, getter=isDone) BOOL done;

然后您可以编写“if(item.done){...}”或“item.done = NO;”,编译器仍将生成属性访问的-isDone。

感谢Chris,希望这可以帮助某人。


1
当我尝试使用这个方法时,我在iOS 4.x上遇到了崩溃。以下是错误信息:“属性'bar'是类'Foo'上的标量类型。无法为其生成getter方法。”我已经尝试在Core Data模型中将属性类型设置为布尔值和16位整数。但无论哪种方式都会导致相同的崩溃。我是否漏掉了什么?也许我应该回到使用NSNumber。 - Josh Brown
2
据我所知,这在NSManagedObject子类上不起作用。 - flagoworld

2

补充一下@RickiG的回答,使用Swift(至少从v4.2开始),创建NSNumber对象和布尔值之间的转换方式如下:

let nsNumberFromBool = NSNumber(booleanLiteral: true) // or false
let boolFromNSNumber = nsNumberFromBool.boolValue

0

对于这个问题的“修复”(在我看来,这是苹果SDK中的一个错误),是将以下代码添加到您的CoreData生成的类中。注意:如果您在一个单独的文件中使用分类进行此操作,则每次在Xcode内重新生成CoreData类时都不必重新复制/粘贴它。

- (BOOL)useGPS
{
    [self willAccessValueForKey:@"useGPS"];
    BOOL myuseGPS = [[self primitiveUseGPS] boolValue];
    [self didAccessValueForKey:@"useGPS"];
    return myuseGPS;
}

- (void)setUseGPS:(BOOL)newValue
{
    [self willChangeValueForKey:@"useGPS"];
    [self setPrimitiveUseGPS:[NSNumber numberWithBool:newValue]];
    [self didChangeValueForKey:@"useGPS"];
}

当我编译时,这会导致类型冲突。我应该更改现有NSNumber属性的类型吗? - Daniel Wood
@Daniel Wood - 不要更改现有的类型:CoreData 要求它们为 NSNumber。编译警告很烦人 - 简单的解决方法是将上述两种方法重命名为 "useGPSAsBool" 和 "setUseGPSAsBool"。注意:您仍然可以访问该属性,只是现在称为 "GPSAsBool",例如 "if( myCoreDataObject.GPSAsBool )"。 - Adam
在阅读了文档后,我决定不再烦恼这些问题,而是直接在我的代码中从NSNumber进行转换:“允许Core Data管理自己的存储的优点通常优于直接与标量值交互的任何优点”。http://developer.apple.com/library/iOS/#documentation/Cocoa/Conceptual/CoreData/Articles/cdNSAttributes.html - Daniel Wood
@Daniel - 你引用的文本是指另一个问题。那个文本在这种情况下不适用 - 我们确实“允许Core Data管理自己的存储”,我们只是添加了两个方便的方法,使它以ObjectiveC期望的方式使用布尔值。我预计苹果最终会添加一个与此基本相同的修复程序到他们自己的代码中。 - Adam

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接