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文件,它将为CoreData
的Boolean
types创buildNSNumber
属性。
但是,您可以使用Bool作为Swifttypes而不是NSNumber, 但是对于我而言,不使用点语法 。 它会设置一个NSNumber
Swift Bool
,这可能会导致点语法错误。
为了使它明确,你应该使用Boolean
types的实体中的属性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文件中使用Bool
types!
所以我认为这是一个错误。
从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在底层做了什么。
我发现,如果你在数据模型中指定类名和模块(而不是保留默认的NSManagedObject
),它就可以正常工作。
一旦我设置了,我可以使用Bool
, Int16
, Int32
等,没有任何问题。