うるおいらんど

【Swift 3】NSPredicateでDateを扱うとき【CoreData】

CoreDataDateSwift

追記があります。

今回はちょっと寄り道編。

CoreDataでDateを保存した際の取り出し方についてです。

 

まずは現在の時刻を保存するところから。

import CoreData

/* 〜〜 */
func saveData(){
        let appDelegate:AppDelegate = UIApplication.shared.delegate as! AppDelegate
        let context:NSManagedObjectContext = appDelegate.managedObjectContext
        let entity = NSEntityDescription.entity(forEntityName:"Person",in:context)
        let person = NSManagedObject(entity:entity!,insertInto:context) as! Person
        //現在の時刻を取得
        let date = NSDate()
        person.date = date
        do{
            try context.save()
        }catch{
            print(error)
        }
}

 

詳しいところはとりあえず【Swift 3】CoreDataを使ってみた【part1】にて。

part1では時刻は保存していませんが、parsonのattributeにdateが追加されている状態として見てください・・・。

 

そしてこれを読み込む時なんですが、

例えば「2016年10月17日のデータを取り出したい」というとき。

 

まずこれは失敗した方です。

import CoreData

/* ~~ */

    func readData(date:Date){
        let appDelegate = UIApplication.shared.delegate as! AppDelegate
        let context:NSManagedObjectContext = appDelegate.managedObjectContext
        let fetchRequest:NSFetchRequest<Person> = Person.fetchRequest()
        let predicate = NSPredicate(format:"date == %@",date)
        fetchRequest.predicate = predicate
        let fetchData = try! context.fetch(fetchRequest)
        if(!fetchData.isEmpty){
            for i in 0 ..< fetchData.count{
                print("fetchData\(fetchData[i].date)")
            }
        }
    }

 

欲しいデータは「2016年10月17日」のデータですが、保存時のデータは「2016年10月17日15時23分35秒」といったところまで含んでいます。

 

つまりラインを引いたところが間違いで、

「2016年10月17日」 == 「2016年10月17日15時23分35秒」ではないので、欲しいデータが得られません。

 

 

ちょっと荒っぽいやり方になってしまいましたが、とりあえず解決策(´・ω・`)

    func readData(date:Date){
        // XX月XX日0時0分0秒に設定したものをstartにいれる
        var component = NSCalendar.current.dateComponents([.year, .month, .day], from: date)
        component.hour = 0
        component.minute = 0
        component.second = 0
        let start:NSDate = NSCalendar.current.date(from:component)! as NSDate
        
        //XX月XX日23時59分59秒に設定したものをendにいれる
        component.hour = 23
        component.minute = 59
        component.second = 59
        let end:NSDate = NSCalendar.current.date(from:component)! as NSDate
        
        let appDelegate = UIApplication.shared.delegate as! AppDelegate
        let context:NSManagedObjectContext = appDelegate.managedObjectContext
        let fetchRequest:NSFetchRequest<Person> = Person.fetchRequest()
        // XX月XX日0時0分0秒からXX月XX日23時59分59秒までのデータを探す
        let predicate = NSPredicate(format:"(date >= %@) AND (date <= %@)",start,end)
        fetchRequest.predicate = predicate
        let fetchData = try! context.fetch(fetchRequest)
        if(!fetchData.isEmpty){
            for i in 0 ..< fetchData.count{
                print("fetchData\(fetchData[i].date)")
            }
        }
    }

 

0時0分0秒から23時59分59秒までのデータを探してくれ!ということなんですが、まぁそのまんまですね。

なんとかうまい書き方がないもんかと思いますが・・・

 

ちなみにNSPredicateを用いる時はDateではなくNSDateじゃないとだめらしいです。

 

とりあえず何でも記事にしとけ!ってことでメモ書きしていますが、何かの参考になればと思います・・・。

 

参考リンク

Additional Notes追記

Swift4でチェック済みです。 NSCalendarの部分だけCalendarで良いかも。

でもNSDateはNSDateじゃないとダメですね。 基本的にそのまま動くはずです。

Comments

コメントはありません。

現在コメントフォームは工事中です。