核心数据代码生成器如何决定是否将属性设为可选?

时间:2019-03-02 02:58:40

标签: swift xcode core-data

我正在macOS 10.13.6 High Sierra上使用Xcode 10 + Swift 4.2。我已经创建了数据模型,并让Core Data自动为数据模型实体生成类。在大多数情况下,这可以按预期进行。但是,我无法弄清楚如何预测所生成的类中的某些属性是否将为Optional类型。它似乎并不取决于相应的属性是否被声明为“可选”(即,在属性说明中选中了“可选”复选框)。有人可以帮我弄清楚Xcode如何弄清楚是否使类属性可选吗?

这是我从项目中得到的一个小例子。我只是将项目专用名称替换为虚构名称,但其他所有内容都相同。首先,这里是数据模型的摘录,用于描述Foo实体:

<entity name="Foo" representedClassName="Foo" parentEntity="FooParent" syncable="YES" codeGenerationType="class">
  <attribute name="v1" attributeType="Date" usesScalarValueType="NO" syncable="YES"/>
  <attribute name="v2" attributeType="Boolean" usesScalarValueType="YES" syncable="YES"/>
  <attribute name="v3" optional="YES" attributeType="Boolean" usesScalarValueType="YES" syncable="YES"/>
  <attribute name="v4" optional="YES" attributeType="UUID" usesScalarValueType="NO" syncable="YES"/>
  <attribute name="v5" optional="YES" attributeType="String" syncable="YES"/>
  <relationship name="v6" toMany="YES" deletionRule="Nullify" destinationEntity="Bar"
                inverseName="baz" inverseEntity="Bar" syncable="YES"/>
</entity>

如您所见,v1,v2和v6在数据模型中未声明为可选,而v3,v4和v5被声明为可选。这是生成的代码,我在项目的Xcode / DerivedData文件夹下的Foo + CoreDataProperties.swift中找到了该代码。

extension Foo {
    @nonobjc public class func fetchRequest() -> NSFetchRequest<Foo> {
        return NSFetchRequest<Foo>(entityName: "Foo")
    }

    @NSManaged public var v1: Date?
    @NSManaged public var v2: Bool
    @NSManaged public var v3: Bool
    @NSManaged public var v4: UUID?
    @NSManaged public var v5: String?
    @NSManaged public var v6: NSSet?

}

如您所见,v2和v3不是可选的,而v1,v4,v5和v6是可选的,这与数据模型中的可选/非可选分配不同。

有人可以帮助我理解Core Data如何确定生成的类属性是可选的还是非可选的?

一方面,我发现自己写着v!.something,我希望我可以写v.something,因为v在数据模型中是非可选的,因此肯定会有存在一些值(假设Core Data正在强制执行非可选属性)。

另一方面,我想为属性let v = v { ... }编写v,该属性在数据模型中是可选的,因此可能存在或可能不存在值。 Xcode给我有关该构造的错误,但是我不能省略测试-我已经知道v的某些实例将不存在。尝试通过写if v != nil { v! }来解决问题的方法失败了-Xcode给出了一个错误,提示您无法解开非可选值(并警告有关将非可选值与nil进行比较)。

在此先感谢您提供的帮助。

编辑:关于与可选属性相对应的非可选属性的最后一点,我看到我可以省略!并写成if v != nil { v }-当然,关于比较非-nil的可选参数仍然存在,但是错误消失了。所以这是一种解决方法。

2 个答案:

答案 0 :(得分:1)

核心数据仍然植根于Objective-C。因此,原语(boolintfloat等)将是非可选的,而对象将是可选的。

某些数据可以是对象或图元。例如,某人的年龄可以是NSNumberNSInteger。如果您希望此类变量由原语支持,则可以在模型的属性的scalar框中选中。

答案 1 :(得分:0)

我认为您可以查看attribute标签,其中有optional="YES"。它决定该属性是否为可选。您可以通过未选中optional中的Data Model insepector

进行更改

enter image description here