如何在Swift中表示Core Data可选标量(Bool/Int/Double/Float)?

64

(首次注意到:Xcode 8.2.1,iOS 10,Swift 3) (仍然存在于:Xcode 9 beta 3,iOS11,Swift 4)

我们都知道Core Data中的optionals概念先于并不严格绑定于Swift中的optionals概念。

即使将Core Data属性标记为Non-optional,我们也已经接受了自动生成的NSManagedObject子类具有optional类型的事实:

(有些人手动删除?而没有任何负面影响,而有些人则不这样做,但这并不重要)

(从这里开始,示例和屏幕截图适用于Bool属性,但同样适用于Int16 / 32/64DoubleFloat

现在我注意到了反面情况 - 当一个类型为BoolCore Data属性标记为Optional(并且选择了Use Scalar Type,这是Xcode默认的),自动生成的类具有非可选类型的变量。

这是否有意义?这是一个错误吗?这种行为在哪里有记录?

最重要的是 - 我如何表示可选的Bool

我可以想到一些解决方法,但它们似乎并不理想(例如,不使用标量,而是回到BoolNSNumber表示。或者(更糟糕的是)有一个单独的名为isVerified_isSetBool


注意:我做了几个测试,如果“默认值”设置为“None”或“NO”,那么即使我在代码中从未实际分配变量,该变量也会保存为“false”。 如果“默认值”设置为“YES”,则变量将保存为“true”。 但是,这意味着(显然)没有办法逻辑地表示此变量尚未设置。

1
你解决了如何表示布尔属性尚未设置的问题吗? - Shamsiddin Saidov
1
@Shamsiddin - 苹果方面没有任何更改/修复 - 因此您仍然需要使用解决方法(辅助isSet属性)或者可能使用Arek答案中链接文章中的建议。 - Nikolay Suvandzhiev
我认为其中一个临时解决方案是在实体类文件中使用Integer 16(NSNumber)来代替Boolean(NSNumber)的true/false,并将其值设为01 - Shamsiddin Saidov
4个回答

41
我看到同样的情况,并认为这是一个bug。在我找到的文档中没有任何记录。显然,Core Data在这里应用了Objective-C风格的假设,其中布尔值默认为NO,而整数默认为0。Core Data/Swift接口存在一些不完善之处,这是我之前没有考虑过的问题。
这是一个很好的发现,但我认为你只能等待苹果公司解决它。你已经知道了最好的解决方法,我也同意这些方法并不理想。我建议提交一个bug报告。

感谢您的回答。实际上,在您提到之前,我甚至没有意识到所有标量类型都会发生相同的“问题”,而不仅仅是Bool。(现在我已经修改了原始问题以提及这一点)。 - Nikolay Suvandzhiev
我不认为这是一个 bug。Core Data 在底层是 objective-c,因此在发布 swifty Core Data 之前,请期望 objective-c 的行为。 - Victor Engel
2
许多苹果框架在底层都是ObjC,但如果支持使用Swift,它们应该呈现Swifty接口。 - Tom Harrington
这不是一个 bug 而是一整个 "狗屎堆"。时间过了这么久,还是没有解决方案。我已经检查了很多解决方法,而我宁愿不保留数据也不愿意使用那些解决方法。现在我真的想知道谁会使用 Core Data,为什么苹果还要维持它,因为这样一个基本而又最重要的功能确实缺失了。这就像带有泛型类型的协议一样。两者都像是由实习生编写而从未经过审核,但苹果决定尝试一下。 - Farid

13

10

我更愿意使用Objective-C类型来管理这些情况,而不是Swift类型。 对于标量类型,可以使用NSNumber。

 @NSManaged public var myDouble: NSNumber?

在这个模型中,myDouble是一个默认为nil值的可选双精度浮点数。
要获取实际值,只需要使用以下代码:
myEntity.myDouble?.doubleValue

那仍然是可选的。你没有解决任何问题。 - Farid
1
问题是如何表示可选的标量值,因此使用可选的NSNumber是一个有效的解决方案。 - 93sauu

1

如果你看到了这里:

@NSManaged var boolAttribute: Bool

如果你已经在这些属性上禁用了“Optional”并启用了“使用标量类型”,但在Objective-C中没有看到它,请确保你已将Swift桥接头文件导入该Objective-C文件。我没有这样做,结果我把我的布尔值改成了NSNumbers,然后我意识到自己多么愚蠢。

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