Swift中如何从Core Data的EntityDate实体获取指定属性
我一眼就看出问题出在哪了——你每次调用addToCoreData都会新建一个EntityDate实体对象,而不是在同一个对象里同时设置date和time属性。从你给出的输出就能看出来:
[<EntityDate: 0x6000034fc2d0> (entity: EntityDate; id: 0xc229f3dcff76efb1 x-coredata://2E6F1D46-F49D-436C-9608-FEC59EEB21E6/EntityDate/p18; data: { date = "2/21/20"; time = nil; }), <EntityDate: 0x6000034fc320> (entity: EntityDate; id: 0xc229f3dcff72efb1 x-coredata://2E6F1D46-F49D-436C-9608-FEC59EEB21E6/EntityDate/p19; data: { date = nil; time = "13:46"; })]
这两个EntityDate实例是完全独立的:第一个是你存date时创建的,第二个是存time时创建的,所以它们各自只有一个属性有值,另一个自然是nil。
修复方案:创建或更新同一实体对象
我们需要修改数据操作逻辑,让它可以找到已存在的实体并更新属性,而不是每次都新建对象。这里假设你希望date和time属于同一条记录(比如同一个日期对应一个时间),可以按以下步骤修改:
1. 优先使用Core Data生成的实体子类
首先建议你给EntityDate生成NSManagedObject子类(Xcode中选择实体 → Editor → Create NSManagedObject Subclass...),这样可以直接用属性访问(比如entity.date),比value(forKey:)更安全易读。
2. 编写「创建/更新」二合一的函数
替换你原来的addToCoreData,用这个函数来处理数据存储:
func addOrUpdateEntityDate(date: String?, time: String?) { let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext // 假设用date作为查询条件,找对应的实体(可根据你的业务逻辑调整) let request: NSFetchRequest<EntityDate> = EntityDate.fetchRequest() if let targetDate = date { request.predicate = NSPredicate(format: "date == %@", targetDate) } do { let results = try context.fetch(request) let targetEntity: EntityDate if let existingEntity = results.first { // 找到已有实体,更新属性 targetEntity = existingEntity targetEntity.date = date ?? targetEntity.date targetEntity.time = time ?? targetEntity.time } else { // 没有找到,创建新实体 targetEntity = EntityDate(context: context) targetEntity.date = date targetEntity.time = time } try context.save() print("数据保存/更新成功") } catch { print("保存/更新失败: \(error.localizedDescription)") } }
3. 正确调用函数存储数据
- 第一次存日期时:
addOrUpdateEntityDate(date: getDateFormatted(), time: nil) - 之后存对应时间时:
addOrUpdateEntityDate(date: getDateFormatted(), time: getFormattedTime())
这样操作后,date和time就会存在同一个EntityDate实例里了。
正确提取数据
修改你的查询函数,直接返回EntityDate类型的数组(比NSManagedObject更直观):
func getEntityDates() -> [EntityDate] { let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext let request: NSFetchRequest<EntityDate> = EntityDate.fetchRequest() request.returnsObjectsAsFaults = false do { return try context.fetch(request) } catch { print("查询失败: \(error.localizedDescription)") return [] } }
提取所有日期和时间
如果要分别获取所有非空的date和time,可以用compactMap过滤掉nil值:
let allEntityDates = getEntityDates() let allDates = allEntityDates.compactMap { $0.date } let allTimes = allEntityDates.compactMap { $0.time } print("所有日期: \(allDates)") print("所有时间: \(allTimes)")
提取单条记录的日期和时间
如果要获取某条记录的对应属性:
if let firstEntity = allEntityDates.first { if let date = firstEntity.date { print("日期: \(date)") } if let time = firstEntity.time { print("时间: \(time)") } }
内容的提问来源于stack exchange,提问作者firozaqiwu

