使用CoreData如何配置获取请求以查找即将到来的生日?

时间:2016-04-15 03:45:10

标签: ios swift core-data nspredicate nsfetchrequest

我正在使用Xcode 7.3和Swift 2.2和NSFetchedResultsController。是否可以创建使用谓词和排序描述符配置的所需获取请求来解决此问题?

如果Person实体具有birthDate属性,如何配置获取请求以返回即将到来的生日?这是我尝试过的:

  1. 我创建了一个名为birthDateThisYear的瞬态属性,并将其配置为今年返回此人的生日。但我发现你不能在使用Core Data的获取请求中使用transient属性。

  2. 我通过使用birthDateDayNumberbirthDateMonthNumber属性以及birthDate的自定义设置器进行非规范化来尝试接受的答案here,但我无法弄清楚谓语。如果今天是12月31日怎么办?不知何故,需要包括Jan,Feb和Mar.

  3. 我读过它可以用表达式和比较谓词来完成。但我无法找到解决方案。任何人都有这个工作?

  4. 我认为创建一个名为birthDateInYear2000的非规范化属性是有效的,但同样,它会遇到相同的重叠问题。

  5. 有什么想法吗?

2 个答案:

答案 0 :(得分:4)

建议:

  • 获取所有生日。
  • 将生日映射到现在的下一个事件

    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包含所有即将升级的生日。

在核心数据中,您可以使用birthday和objectID(或全名)获取记录作为字典,创建临时结构,映射和排序项目并获取objectID的人(或使用全名) - 或者您甚至可以将逻辑应用于NSManagedObject数组

修改

如果有关下一个生日的信息存储在持久性商店中(假设它是MySQL商店),则使用NSFetchedResultsController您可以对表格视图排序进行排序,因为您可以' t应用排序描述符,包括指向瞬态或计算属性的键。

更新nextBirthDate属性的最佳位置就在创建视图控制器的NSFetchedResultsController实例之前。

  • 在实体nextBirthDate
  • 中创建(可选)属性Person
  • 创建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
       ...
    
  • 如果视图控制器可以编辑birthDate属性,请不要忘记更新nextBirthDate属性以保持视图同步。

答案 1 :(得分:0)

我的建议很相似:

  • 取得所有客户/人
  • 过滤3天前和3天后的所有出生日期

使用如下的闭包:

func fetchBirthdayList(){
    // this example considers all birthdays that are like
    // |---TODAY---|
    // Each hyphen represents a day
    let date = Date()
    let timeSpan = 3
    let cal = Calendar.current
    nextBirthDays = self.list.filter { (customer) -> Bool in
        if let birthDate = customer.birthDate {
            let difference = cal.dateComponents([.day,.year], from: birthDate as! Date, to: date)
            return (( (difference.day! <= timeSpan) || ((365 - difference.day!) <= timeSpan) ) && difference.day! >= 0)
        }
        return false
    }
}

如果需要,您可以在之后订购结果。

干杯

奥利弗