Core Data codegen 如何决定是不是将属性设为可选?

Posted

技术标签:

【中文标题】Core Data codegen 如何决定是不是将属性设为可选?【英文标题】:How does Core Data codegen decide whether to make a property optional?Core Data codegen 如何决定是否将属性设为可选? 【发布时间】:2019-03-02 02:58:40 【问题描述】:

我正在 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 正在强制执行非可选属性)。

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

提前感谢您对此提供的任何启示。

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

【问题讨论】:

这可能会有所帮助:***.com/questions/25485273/… @MikeTaverne 感谢您的链接。我的问题和那个差不多。作为记录,我发现第二个投票较少的答案更有帮助:***.com/a/43827209/871096 【参考方案1】:

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

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

【讨论】:

【参考方案2】:

我想你可以看看attribute 标签,那里有optional="YES"。它决定该属性是否是可选的。您可以通过 Data Model insepector 中未选中的 optional 进行更改

【讨论】:

感谢您的回复。不幸的是,复选框是否被选中并不能确定该属性是否在生成的类中声明为可选,正如您在示例中看到的 v1(在数据模型中不是可选但在类属性中是选项),v2(在数据模型,在类中不是可选的)和 v3(在数据模型中是可选的,在类中不是可选的)。 我建议您手动生成Foo+CoreDataProperties.swift 并按预期删除?。它应该可以正常工作,这似乎是一个限制。 核心数据中的可选复选框不会转化为 Swift 中的可选概念。见***.com/questions/33548350/…

以上是关于Core Data codegen 如何决定是不是将属性设为可选?的主要内容,如果未能解决你的问题,请参考以下文章

如何将字符串保存到Core Data Swift

../../build/debug/codegen/libCodeGen.a(llvm-codegen.cc.o ):( data.rel.ro_ZTIN4llvm18ValueMapCallback

如何检查关系是不是已建立 - Core Data

Core Data Migration 将如何适用于两个项目?

如何测试 Core Data SQLite 文件是不是已加密?

Core Data - 如何检查用户是不是存在于数据库中?