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

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

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じゃないとだめらしいです。

 

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

 

2018/04/14追記
Swift4でチェック済みです。
NSCalendarの部分だけCalendarで良いかも。

でもNSDateはNSDateじゃないとダメですね。
基本的にそのまま動くはずです。
Swift , ,
コメントは認証制です。詳しくは下記の注意をお読みください。お気軽にコメントお願いします!

Write a Comment

コメント時の注意

「Twitter」「Facebook」「Google+」「WordPress」のいずれかのアカウントをお持ちの方は各アカウントと連携することでコメントできます。 コメントしたことはSNSに流れませんので、アカウントをお持ちの方はこちらの方法でコメントを投稿して下さると嬉しいです。 アカウントをお持ちでない方はメールアドレスで投稿することができます。 初回コメント時は承認後に表示されます。

Related Memo...

記事を書くほどでもないけれどメモっておきたいこと

テスト投稿。

例えばiphone7 の画面サイズ

750 × 1334
半分375 × 667

iOS
more