Return 从现在起 1 个月后存储在 Core Data 中的所有生日
Return all birthdays stored in Core Data that occur 1 month from now
我在 Core Data 中存储生日列表,并且我在 Core Data 中使用 NSFetchedResultsController
到 return 所有生日。我遇到的主要问题是年份。我想显示一个月后的生日。但是如你所知,一个人可能出生于 2005 年 10 月 18 日,但将它与一个月后的日期进行比较是行不通的,因为假设今天是 2016 年 10 月 15 日,我会将 2016 年 11 月 1 日与 2005 年 10 月 18 日进行比较所以我的应用程序会认为生日不会在一个月后发生。如何使用 NSPredicate 检查下个月是否是生日?
这是我现在正在使用但没有成功的一些代码:
class BirthdayFetchedResultsController: NSFetchedResultsController<Birthday>, NSFetchedResultsControllerDelegate {
private let tableView: UITableView
init(managedObjectContext: NSManagedObjectContext, tableView: UITableView) {
self.tableView = tableView
let request: NSFetchRequest<Birthday> = Birthday.fetchRequest()
let dateSortDescriptor = NSSortDescriptor(key: "date", ascending: true)
request.sortDescriptors = [dateSortDescriptor]
let startOfDay = Calendar.current.startOfDay(for: Date()) as NSDate
// FIXME: The year matters here when it shouldn't.
let predicate = NSPredicate(format: "date >= %@", startOfDay)
request.predicate = predicate
// TODO: Add section name key path for sorting the birthdays into sections
super.init(fetchRequest: request, managedObjectContext: managedObjectContext, sectionNameKeyPath: nil, cacheName: nil)
self.delegate = self
tryFetch()
}
func tryFetch() {
do {
try performFetch()
} catch let error as NSError {
// TODO: Implement Error Handling
print("Unresolved error: \(error), \(error.userInfo)")
}
}
}
更新:
现在,我知道如何处理这个问题了。月份必须小于或等于当前月份加 1,可以小于当前月份减 11,或者月份可以相同但日期必须大于。我试图为此构建一个谓词,但它似乎不起作用:
let calendar = Calendar.current
let now = Date()
let month = calendar.component(.month, from: now)
let date = calendar.component(.day, from: now)
let predicate = NSPredicate(format: "((month <= %@) or (month <= %@)) or ((month == %@) AND (date >= %@))", argumentArray: [month + 2, month - 10, month, date])
request.predicate = predicate
如果您要查找在下周或下个月发生的生日等重复事件的所有实例,那么 "date" 属性不是一个好的选择。充其量,获得您需要的结果将是非常尴尬的。 Core Data 中的一个日期对应于一个 Swift Date
,它代表一个瞬间并且不存储诸如月份或月份之类的详细信息。
最好以您需要的形式存储这些详细信息,例如月份和日期的整数值。这使得查找变得相当简单,因为您有存储需要用作过滤器的值的字段。确实没有什么好方法可以根据需要使用日期属性。一个糟糕的方法是计算过去 N 年的每一年的月份间隔(无论 N 你 select)并构建一个结合所有这些的大型谓词。不推荐。
您还必须处理 12 月的特殊情况,其中当前日期可能是 12 月 18 日,生日是 01 月 1 日。在这种情况下,它不会检测到生日即将到来,因为 12 > 1.
这是一个示例谓词:
// Month Conditions
let monthCondition1 = NSPredicate(format: "month <= %i", month + 1)
let monthCondition2 = NSPredicate(format: "month > %i", month)
let monthConditions = NSCompoundPredicate(andPredicateWithSubpredicates: [monthCondition1, monthCondition2])
// Date Conditions
let dateCondition1 = NSPredicate(format: "month == %i", month)
let dateCondition2 = NSPredicate(format: "date >= %i", date)
let dateConditions = NSCompoundPredicate(andPredicateWithSubpredicates: [dateCondition1, dateCondition2])
// Special Month Condition - Example: If currentDate is 12/31 and the birthday is 01/01 current month is greater than birthday but we still show it.
var predicate = NSCompoundPredicate(orPredicateWithSubpredicates: [monthConditions, dateConditions])
if month == 12 {
let specialMonthCondition1 = NSPredicate(format: "month == %i", 1)
predicate = NSCompoundPredicate(orPredicateWithSubpredicates: [predicate, specialMonthCondition1])
}
request.predicate = predicate
我在 Core Data 中存储生日列表,并且我在 Core Data 中使用 NSFetchedResultsController
到 return 所有生日。我遇到的主要问题是年份。我想显示一个月后的生日。但是如你所知,一个人可能出生于 2005 年 10 月 18 日,但将它与一个月后的日期进行比较是行不通的,因为假设今天是 2016 年 10 月 15 日,我会将 2016 年 11 月 1 日与 2005 年 10 月 18 日进行比较所以我的应用程序会认为生日不会在一个月后发生。如何使用 NSPredicate 检查下个月是否是生日?
这是我现在正在使用但没有成功的一些代码:
class BirthdayFetchedResultsController: NSFetchedResultsController<Birthday>, NSFetchedResultsControllerDelegate {
private let tableView: UITableView
init(managedObjectContext: NSManagedObjectContext, tableView: UITableView) {
self.tableView = tableView
let request: NSFetchRequest<Birthday> = Birthday.fetchRequest()
let dateSortDescriptor = NSSortDescriptor(key: "date", ascending: true)
request.sortDescriptors = [dateSortDescriptor]
let startOfDay = Calendar.current.startOfDay(for: Date()) as NSDate
// FIXME: The year matters here when it shouldn't.
let predicate = NSPredicate(format: "date >= %@", startOfDay)
request.predicate = predicate
// TODO: Add section name key path for sorting the birthdays into sections
super.init(fetchRequest: request, managedObjectContext: managedObjectContext, sectionNameKeyPath: nil, cacheName: nil)
self.delegate = self
tryFetch()
}
func tryFetch() {
do {
try performFetch()
} catch let error as NSError {
// TODO: Implement Error Handling
print("Unresolved error: \(error), \(error.userInfo)")
}
}
}
更新: 现在,我知道如何处理这个问题了。月份必须小于或等于当前月份加 1,可以小于当前月份减 11,或者月份可以相同但日期必须大于。我试图为此构建一个谓词,但它似乎不起作用:
let calendar = Calendar.current
let now = Date()
let month = calendar.component(.month, from: now)
let date = calendar.component(.day, from: now)
let predicate = NSPredicate(format: "((month <= %@) or (month <= %@)) or ((month == %@) AND (date >= %@))", argumentArray: [month + 2, month - 10, month, date])
request.predicate = predicate
如果您要查找在下周或下个月发生的生日等重复事件的所有实例,那么 "date" 属性不是一个好的选择。充其量,获得您需要的结果将是非常尴尬的。 Core Data 中的一个日期对应于一个 Swift Date
,它代表一个瞬间并且不存储诸如月份或月份之类的详细信息。
最好以您需要的形式存储这些详细信息,例如月份和日期的整数值。这使得查找变得相当简单,因为您有存储需要用作过滤器的值的字段。确实没有什么好方法可以根据需要使用日期属性。一个糟糕的方法是计算过去 N 年的每一年的月份间隔(无论 N 你 select)并构建一个结合所有这些的大型谓词。不推荐。
您还必须处理 12 月的特殊情况,其中当前日期可能是 12 月 18 日,生日是 01 月 1 日。在这种情况下,它不会检测到生日即将到来,因为 12 > 1.
这是一个示例谓词:
// Month Conditions
let monthCondition1 = NSPredicate(format: "month <= %i", month + 1)
let monthCondition2 = NSPredicate(format: "month > %i", month)
let monthConditions = NSCompoundPredicate(andPredicateWithSubpredicates: [monthCondition1, monthCondition2])
// Date Conditions
let dateCondition1 = NSPredicate(format: "month == %i", month)
let dateCondition2 = NSPredicate(format: "date >= %i", date)
let dateConditions = NSCompoundPredicate(andPredicateWithSubpredicates: [dateCondition1, dateCondition2])
// Special Month Condition - Example: If currentDate is 12/31 and the birthday is 01/01 current month is greater than birthday but we still show it.
var predicate = NSCompoundPredicate(orPredicateWithSubpredicates: [monthConditions, dateConditions])
if month == 12 {
let specialMonthCondition1 = NSPredicate(format: "month == %i", 1)
predicate = NSCompoundPredicate(orPredicateWithSubpredicates: [predicate, specialMonthCondition1])
}
request.predicate = predicate