Core Data使用NSManagedObject Subclass管理数据
CCoorree DDaattaa使使NNSSMMaannaaggeeddOObbjjeecctt SSuubbccllaassss

Core Data使用NSManagedObject Subclass管理数据

什么是 NSManagedObject Subclass?

在Core Data中创建一个实体(Entity)时,Xcode只是定义了一个数据模型,但数据模型本身无法直接使用。

因此,需要一个 Swift 类(NSManagedObject 的子类)来:

1)直接操作 Core Data 中的对象。

2)访问和修改实体的属性。

3)执行 CRUD(创建、读取、更新、删除)操作。

例如,在 .xcdatamodeld 文件中,创建一个名为Eurofxrefhist的实体,并创建三个属性(currencySymbol、date和exchangeRate)字段。

生成NSManagedObject Subclass

在 .xcdatamodeld 文件中,选择 Eurofxrefhist实体 → Editor → Create NSManagedObject Subclass。

勾选对应的实体数据模型。

勾选对应的实体。

选择NSManagedObject Subclass在项目中的存储位置。

NSManagedObject Subclass文件

[EntityName]+CoreDataClass.swift

import Foundation
import CoreData

@objc(Eurofxrefhist)
public class Eurofxrefhist: NSManagedObject {

}

这是 NSManagedObject 的子类,表示 Core Data 实体的 Swift 类。

Eurofxrefhist 继承自 NSManagedObject,可以用于创建和操作 Core Data 对象。

这个文件通常不需要修改,但可以在这里添加自定义逻辑,比如:

加额外的方法

处理数据的特殊逻辑

[EntityName]+CoreDataProperties.swift

import Foundation
import CoreData

extension Eurofxrefhist {

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

    @NSManaged public var currencySymbol: String?
    @NSManaged public var exchangeRate: Double
    @NSManaged public var date: Date?

}

extension Eurofxrefhist : Identifiable {

}

这个文件是 Eurofxrefhist 的扩展,定义了:

属性:与数据模型中配置的 Attributes 和 Relationships 一一对应。

fetchRequest():用于获取 Eurofxrefhist 数据的请求方法。

这个文件通常是自动生成的,不建议直接修改。

不生成 NSManagedObject Subclass 可以吗?

可以不生成,但会失去很多便利,导致开发过程变得复杂。

如果不生成 NSManagedObject Subclass

只能通过 NSManagedObject 的通用 API 来操作数据。

不能使用属性点语法(如 task.title),需要手动使用 setValue(_:forKey:) 和 value(forKey:)。

必须手动创建 NSFetchRequest,并指定实体名和属性名作为字符串,容易出错。

如果生成 NSManagedObject Subclass

可以像操作普通 Swift 类一样访问属性(如 task.title)。

Xcode 会自动生成 fetchRequest(),方便进行数据查询。

数据访问更加安全、直观、易于维护。

示例对比

使用 NSManagedObject Subclass

// 创建对象
let newTask = Task(context: viewContext)
newTask.title = "Learn Core Data"
newTask.createdAt = Date()

// 保存数据
try? viewContext.save()

// 读取数据
let fetchRequest: NSFetchRequest<Task> = Task.fetchRequest()
let tasks = try? viewContext.fetch(fetchRequest)

不使用 NSManagedObject Subclass

// 创建对象
let entity = NSEntityDescription.entity(forEntityName: "Task", in: viewContext)!
let newTask = NSManagedObject(entity: entity, insertInto: viewContext)
newTask.setValue("Learn Core Data", forKey: "title")
newTask.setValue(Date(), forKey: "createdAt")

// 保存数据
try? viewContext.save()

// 读取数据
let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "Task")
let tasks = try? viewContext.fetch(fetchRequest)
for task in tasks ?? [] {
    print(task.value(forKey: "title") as? String ?? "No Title")
}

生成 NSManagedObject Subclass 的好处

1、简化代码

直接使用 Swift 属性访问数据,不再需要 setValue 和 value(forKey:)。

2、自动生成 fetchRequest()

可以直接使用 Task.fetchRequest() 来创建数据请求,省去手写字符串。

3、类型安全

属性有明确的类型,不会因为拼写错误或属性名变化导致崩溃。

4、方便扩展

可以自定义方法,扩展 Task 或 Eurofxrefhist 类的功能。

什么时候需要重新生成 NSManagedObject Subclass?

当发生以下场景时:

新增或删除属性(Attributes)。

修改实体的名称。

增加或删除关系(Relationships)。

注意

重新生成时,如果手动修改了 CoreDataClass 或 CoreDataProperties 文件中的内容,需要注意不要覆盖或丢失自定义逻辑。

如果想要在 CoreDataClass 中添加自定义代码,可以将逻辑写在单独的 extension 里,以避免重新生成时被覆盖。

总结

Create NSManagedObject Subclass 是生成 Core Data 实体 Swift 类的工具,极大地简化了数据操作。

强烈建议使用它,这样可以更方便地操作 Core Data 对象,不需要手动处理数据的 Key-Value 形式。

如果不生成 NSManagedObject Subclass,会使操作数据的代码复杂很多,并且容易出错。

扩展知识

“Multiple commands produce…”报错

在创建NSManagedObject Subclass后,Xcode可能报如下错误:

'Eurofxrefhist' is ambiguous for type lookup in this context
'Eurofxrefhist' is ambiguous for type lookup in this context

报错信息表示,Xcode 在多个地方找到了 Eurofxrefhist 类型,不知道该使用哪个。

解决方案

从网络上找到两篇贴文《‘Class’ is ambiguous for type lookup in this context》和《Invalid redeclaration on CoreData classes》。

解决方案为:

1)删除已经生成的两个NSManagedObject Subclass文件

2)使用快捷键“Command + Shift + K”清理构建文件夹。

3)打开 .xcdatamodeld 文件,点击Entities实体,点击右侧扩展栏。

4)在Class中,Module设置为Current Product Module,Codegen设置为Manual/None。

5)选择 Eurofxrefhist实体 → Editor → Create NSManagedObject Subclass。重新生成NSManagedObject Subclass。

6)生成NSManagedObject Subclass文件后,按Command + B构建,不再报错。

相关文章

‘Class’ is ambiguous for type lookup in this context:https://stackoverflow.com/questions/52496584/class-is-ambiguous-for-type-lookup-in-this-context

Invalid redeclaration on CoreData classes:https://stackoverflow.com/questions/40410169/invalid-redeclaration-on-coredata-classes

如果您认为这篇文章给您带来了帮助,您可以在此通过支付宝或者微信打赏网站开放者。

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注