我使用 Xcode 7.3 和 Swift 2.2 以及 NSFetchedResultsController
。是否可以创建配置有谓词和排序描述符的所需获取请求来解决此问题?
给定一个具有 birthDate
属性的 Person
实体,如何配置提取请求以返回即将到来的生日?这是我尝试过的:
我创建了一个名为
birthDateThisYear
的 transient 属性,并将其配置为返回此人今年的生日。但我发现你不能在 Core Data 的获取请求中使用 transient 属性。我尝试了接受的答案 here通过使用
birthDateDayNumber
和birthDateMonthNumber
属性以及birthDate
的自定义 setter 进行非规范化,但我无法弄清楚谓词。如果今天是 12 月 31 日怎么办?不知何故,它需要包含一月、二月和三月。我读到它可以通过表达式和比较谓词来完成。但我想不出解决办法。有人成功了吗?
我认为创建一个名为
birthDateInYear2000
的非规范化属性是可行的,但是,这又遇到了相同的重叠问题。
有什么想法吗?
最佳答案
建议:
- 获取所有生日。
将生日映射到从现在开始的下一次出现
let calendar = NSCalendar.currentCalendar() let nextBirthDays = birthdays.map { (date) -> NSDate in let components = calendar.components([.Day, .Month], fromDate: date) return calendar.nextDateAfterDate(NSDate(), matchingComponents: components, options: .MatchNextTime)! }
对日期进行排序
let sortedNextBirthDays = nextBirthDays.sort { $0.compare($1) == .OrderedAscending }
现在
sortedNextBirthDays
包含所有即将到来的生日,按升序排序。
在 Core Data 中,您可以以包含生日和 objectID(或全名)的字典形式获取记录,创建临时结构,对项目进行映射和排序,并获取 objectID 的人员(或使用全名) - 或者您甚至可以将逻辑应用于 NSManagedObject
数组
编辑
使用NSFetchedResultsController
,仅如果有关下一个生日的信息存储在持久存储中(假设它是 MySQL 存储),则可以对 TableView 进行排序,因为您无法应用排序描述符,包括指向 transient 或计算属性的键。
更新 nextBirthDate
属性的最佳位置是在创建 View Controller 的 NSFetchedResultsController
实例之前。
- 在实体
Person
中创建一个(可选)属性nextBirthDate
创建
NSDate
的扩展来计算从现在起下一次出现的日期extension NSDate { var nextOccurrence : NSDate { let calendar = NSCalendar.currentCalendar() let components = calendar.components([.Day, .Month], fromDate: self) return calendar.nextDateAfterDate(NSDate(), matchingComponents: components, options: .MatchNextTime)! } }
在初始化
NSFetchResultsController
实例的闭包中添加代码来更新每个记录的nextBirthDate
属性lazy var fetchedResultsController: NSFetchedResultsController = { let fetchRequest = NSFetchRequest(entityName: "Person") do { let people = try self.managedObjectContext.executeFetchRequest(fetchRequest) as! [Person] people.forEach({ (person) in let nextBirthDate = person.birthDate.nextOccurrence if person.nextBirthDate == nil || person.nextBirthDate! != nextBirthDate { person.nextBirthDate = nextBirthDate } }) if self.managedObjectContext.hasChanges { try self.managedObjectContext.save() } } catch { print(error) } // Set the batch size to a suitable number. fetchRequest.fetchBatchSize = 20 // Edit the sort key as appropriate. let sortDescriptors = [NSSortDescriptor(key:"nextBirthDate", ascending: true)] fetchRequest.sortDescriptors = sortDescriptors ...
如果 View Controller 可以编辑
birthDate
属性,请不要忘记更新nextBirthDate
属性以保持 View 同步。
关于ios - 使用 CoreData 如何配置获取请求来查找即将到来的生日?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36637896/