Swift + CoreData:无法在NSManagedObject子类上设置Bool – Bug?

我有一个奇怪的问题,我似乎无法弄清楚,我有一个自定义NSManagedObject子类的简单实体:

@objc(EntityTest) class EntityTest: NSManagedObject { @NSManaged var crDate: NSDate @NSManaged var name: String @NSManaged var completed: Bool @NSManaged var completedOn: NSDate } 

这是问题,我可以创build对象罚款,并设置所有的价值和存储在一个数组。 不过最近,当我尝试检索相同的对象时,除了“completed”字段,我可以设置所有的值。 我得到一个运行时错误,说“EXC_BAD_ACCESS”,我可以读取的值,只是无法设置它。

debugging器指向:

 0x32d40ae: je 0x32d4110 ; objc_msgSend + 108 0x32d40b0: movl (%eax), %edx 

也许有些问题是由于它被当作一个Objective-C类,并试图发送消息来设置布尔值,我知道有点有趣的CoreData最初代表他们作为NSNumbers。

有任何想法吗? 我自己创build了这个类,它不是生成的。

编辑:

 entity.crDate = NSDate() // succeeds entity.completed = false // fails entity.completed.setValue(false, forKey: "completed") //succeeds 

所以为了设置bool,使用NSManagedObject的setValue工作,但不是直接设置器,虽然对于非布尔属性,我可以使用setter来设置它。

更新:

虽然再检查一下,这似乎是我第一次从NSEntityDescription获得值后,它使用普通的Swift访问器方法。 后来当我尝试访问同一个对象(存储在一个数组中)时,它试图把它当作一个Objective-C样式对象,并发送一个名为“setCompleted”的方法的消息。 我想这是有道理的,因为我使用点符号来访问它,我用@objc指令。

我通过创build一个“setCompleted”方法来testing这个方法,但是在方法中,我使用“completed = newValue”来设置值,这会使得recursion调用回到“setCompleted”,从而导致它崩溃。奇怪的是,现在仍然可以没有适当的修复。 这似乎只发生在布尔斯身上。

只有解决方法是使用NSManagedObject的“setValueForKey”方法。 也许这是一个错误报告?

如果您让Xcode 6 Beta 3为您的实体创buildSwift文件,它将为CoreDataBooleantypes创buildNSNumber属性。

在这里输入图像说明

但是,您可以使用Bool作为Swifttypes而不是NSNumber, 但是对于我而言,不使用点语法 。 它会设置一个NSNumber Swift Bool ,这可能会导致点语法错误。


为了使它明确,你应该使用Booleantypes的实体中的属性typesNSNumber 。 然后创build一个计算属性(在语言指南 – >属性 – >计算属性下的iBook Swift编程语言 )返回给你一个Swift Bool 。 所以永远不会真的存储一个Bool

像这样:

 @NSManaged var snack: NSNumber var isSnack: Bool { get { return Bool(snack) } set { snack = NSNumber(bool: newValue) } } 

当然,隐藏另一个(NSNumber属性)会很酷,但要耐心一点,苹果将在未来实现私有属性。


编辑:

如果你勾选了创buildskalartypes的框,它甚至会在自动创build的Swift文件中使用Booltypes!

所以我认为这是一个错误。

从CH白金汉以下是完全正确的。 您正试图将核心数据中的原始types存储在期望NSNumber的位置。

正确的用法是entity.completed = NSNumber.numberWithBool(false)

这也是为什么你不能直接检索这个完整的值作为一个布尔,因此你需要写:

 var: Bool? = entity.completed.boolValue() 

你可以将你的属性从NSNumber下注到Booltypes,如下所示:

 var someBoolVariable = numberValue as Bool 

它以这种方式适用于我:

 self.twoFactorAuthEnabledSwitch.enabled = userProfile?.twoFactorEnabled as Bool 

在XCode 8中只需设置:

 user.isLoggedIn = true 

它的作品就像一个魅力

我没有碰到swift,但在Objective-C中,BOOL不是一个对象,不能是一个对象。 这是一个原始的,它看起来像你正在试图告诉一个Objective-C类来对待一个BOOL像一个对象。 但是我可以做到这一点,因为我不熟悉@NSManaged在底层做了什么。

https://developer.apple.com/library/ios/documentation/cocoa/conceptual/ProgrammingWithObjectiveC/FoundationTypesandCollections/FoundationTypesandCollections.html

我发现,如果你在数据模型中指定类名和模块(而不是保留默认的NSManagedObject ),它就可以正常工作。

一旦我设置了,我可以使用BoolInt16Int32等,没有任何问题。