2016-04-15 43 views
2

我使用Xcode 7.3和Swift 2.2以及NSFetchedResultsController。是否可以創建配置謂詞和排序描述符來解決此問題所需的提取請求?使用CoreData如何配置獲取請求以查找即將到來的生日?

鑑於Person具有birthDate屬性的實體如何配置獲取請求以返回即將到來的生日?這是我曾嘗試:

  1. 我創建了一個名爲birthDateThisYear瞬態屬性和配置,今年返回的人的生日。但是我發現,您不能在Core Data的提取請求中使用transient屬性。

  2. 我用birthDateDayNumberbirthDateMonthNumber屬性與birthDate一個定製的setter沿着非規範化試圖接受的答案here但我無法弄清楚謂語。如果今天是12月31日呢?不知何故,它將需要包裝1月,2月和3月

  3. 我讀到它可以完成表達式和比較謂詞。但我找不出解決方案。任何人都有這個工作?

  4. 我認爲它的工作原理是創建一個稱爲birthDateInYear2000的非規範化屬性,但同樣也會遇到同樣的重疊問題。

任何想法?

回答

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包含升序排列所有即將到來的生日。

在覈心數據,你可以提取記錄作爲生日而objectid(或全名)的字典,創建一個臨時的結構,地圖和項目進行排序,並得到了的objectID的人(或使用全名) - 或者你甚至可以將邏輯應用到NSManagedObject陣列

編輯

使用一個NSFetchedResultsController如果對下一個生日的信息存儲在堅持,你可以排序表視圖只(假設它是MySQL存儲),因爲您不能應用排序描述符,包括指向瞬態屬性或計算屬性的鍵。

更新nextBirthDate屬性的最佳位置就在創建視圖控制器的NSFetchedResultsController實例之前。

  • 在實體創建(可選的)屬性nextBirthDatePerson
  • 創建擴展的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屬性以保持視圖同步。

+0

看起來有前途的!我忽略了說我正在使用'NSFetchedResultsController'。你認爲你的答案可以適應嗎?它似乎並不如此。它需要交給配置好的'NSFetchRequest'。 –

+0

我更新了答案建議用'NSFetchedResultsController'的解決方案。唯一的缺點是'nextBirthDate'屬性必須是持久的。 – vadian

+0

好思想!我會試試看。這對於大型數據集可能不太適用,但是這個應用程序的Person實體數量很少。可能不超過25次。 –

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 
    } 
} 

如果你願意,你可以在之後訂購結果。

乾杯

奧利弗