Swift + CoreData: 生成的NSManagedObject子类上无法自动设置可选属性

55

我有一个名为Record的coredata实体,它有一个名为dateUpdated的属性。我注意到生成的NSManagedObject子类没有可选标记(?)

CoreData编辑器:

输入图像描述

生成的子类:

输入图像描述

期望结果:

输入图像描述

更新: 这让我很繁琐,因为每次我想重新生成子类时,这意味着我还需要手动更新所有可选值。 在子类中有一个非可选项(没有'?'),这导致我在赋值之前检查值,例如下面的示例:

// sample value:
// serverDateFormatter = "yyyy/MM/dd"
// dateString = ""    

// Branch is a subclass of Record (see above images)

var date = self.coreData.serverDateFormatter.dateFromString(dateString)
if date != nil
{
   branch.dateUpdated = date 
}

但如果xcode可以使用(?)在子类中自动设置可选值,我只需要这样做:

branch.dateUpdated = self.coreData.serverUTCDateFormatter.dateFromString(dateString)
在我的情况下,我有一堆属性需要手动标记为可选的。

更新:这已经在Xcode 7.1中实现。 - Allan Macatingrao
与 https://dev59.com/TVwX5IYBdhLWcg3wpw5h 相关的编程内容。 - mfaani
我在XCode 11.3.1仍然遇到这个问题。你说的"This is already implemented in Xcode 7.1"是什么意思? - Luke
2个回答

56
在 Swift 和它的可选项被引入之前,Core Data Model Editor 中的可选框已经存在了。关于此,苹果在其Core Data Programming Guide中有所说明:
您可以指定属性是可选的——也就是说,不需要具有值。然而,通常情况下,您不建议这样做——特别是对于数字值(通常使用具有默认值(在模型中)为0的强制属性可以获得更好的结果)。原因是 SQL 对 NULL 有特殊的比较行为,与 Objective-C 的 nil 不同。数据库中的 NULL 与 0 不同,搜索 0 将无法匹配具有 NULL 的列。
因此,在使用 Swift 和 Xcode 8 时,可选框与您是否将属性定义为可选项与您的 managedObject 子类没有关系。并且,当您使用“Editor”>“Create NSManagedObject Subclass”创建它们时,不要期望可选框会对您的NSManagedObject子类属性的可选类型产生任何影响。

话虽如此,但每当我需要在模型编辑器中将属性的可选复选框选中时,我立即将其 NSManagedObject 子类声明为可选项。


附录

Mogenerator 能够自动将你的 NSManagedObject 子类属性从非可选变为可选,每当你在数据模型检查器中更改实体属性的此选项并重新构建项目时。


请看我的更新问题。我理解你的观点。希望发布的Xcode6版本能够支持这种情况。谢谢。我会将你的答案标记为正确。 - Allan Macatingrao
9
这很麻烦。我有很多可选字段。 - Daniel
我看不出来Core Data编程指南中引用的段落与答案的其余部分有什么关系。 - Luke
@Daniel,你在开发生涯中是否曾经有过正当的解决方案?我正在尝试在学习Android之后学习iOS,但这真的很烦人。虽然有一些解决方法,比如在将实体映射到其他层模型时强制解包,但如果你决定在模型中使参数可选(不是在Core Data中),事情很容易变得糟糕。我不想创建NSManagedObject的子类,因为我会失去“级联”删除等好用的功能。 - Farid

9

解决方法:

是的,这似乎是一个错误/限制。使用非标量类型可以解决这个问题。

可选属性

  • 勾选可选复选框
  • 取消标量复选框的勾选

非可选属性

  • 取消可选复选框的勾选
  • 勾选标量复选框

可能的原因:

Swift代码被翻译成Objective-C,而Objective-C不支持非类类型的nil值。


2
我认为你的意思是Objective-C不支持非类(原始)类型的_nil_值。澄清一下:NSNumber类可能为空,但原始类型不能 - 正如你所说,为什么对于可选属性,必须取消标量复选框。 - wardw
感谢您的建议,已进行更正。对于可选属性,请取消标量复选框,以便使用非标量类型,如NSNumber - user1046037
Swift不会被翻译成Objective-C,它直接编译成二进制文件。Swift不是Objective-C的包装器,而是一种独立的语言。 - Alec O
@AlecO,Swift 还不是一门完整的语言。许多东西在底层仍然是 Objective-C。这就是为什么例如 @objc@nonobjc 这样的属性在某些情况下(如 Core Data 类文件)是必需的。此外,任何以 NS 开头的内容仍然基于 Objective-C,例如 NSFetchRequestNSManagedObject。服务器端 Swift(可用于 Linux)由已完成的 Swift 框架组成,没有底层的 Objective-C。你在那里看不到 Core Data,至少目前还没有... - leanne
3
我不太确定如何利用这个解决方法。我想让我的Doubles是可选的,但如果我取消勾选“使用标量类型”,那么我必须为所有东西使用NSNumber,这本身就是一个怪物。 - willbattel
显示剩余2条评论

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