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 正在强制执行非可选属性)。
另一方面,我想为属性v
写let 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。因此原语(bool
、int
、float
等)将是非可选的,而对象将是可选的。
有些数据可以是对象也可以是基元。例如,某人的年龄可能是NSNumber
或NSInteger
。如果您希望此类变量由原语支持,则可以选中 scalar
框以获取模型中的属性。
【讨论】:
【参考方案2】:我想你可以看看attribute
标签,那里有optional="YES"
。它决定该属性是否是可选的。您可以通过 Data Model insepector
中未选中的 optional
进行更改
【讨论】:
感谢您的回复。不幸的是,复选框是否被选中并不能确定该属性是否在生成的类中声明为可选,正如您在示例中看到的 v1(在数据模型中不是可选但在类属性中是选项),v2(在数据模型,在类中不是可选的)和 v3(在数据模型中是可选的,在类中不是可选的)。 我建议您手动生成Foo+CoreDataProperties.swift
并按预期删除?
。它应该可以正常工作,这似乎是一个限制。
核心数据中的可选复选框不会转化为 Swift 中的可选概念。见***.com/questions/33548350/…以上是关于Core Data codegen 如何决定是不是将属性设为可选?的主要内容,如果未能解决你的问题,请参考以下文章
../../build/debug/codegen/libCodeGen.a(llvm-codegen.cc.o ):( data.rel.ro_ZTIN4llvm18ValueMapCallback
Core Data Migration 将如何适用于两个项目?