Maverick447
Maverick447

Reputation: 143

swift coredata query not working for today's date

I have a class named Places managed by CoreData. This object has a Date object as a timestamp.

I have this query to probe for only today's places. The issue is that I have only 2 places logged in today, however it's yielding me 21 records, which I do not expect

func updatePlaceMarksForADateFromDatabase(date: Date) {
    var calendar = Calendar.current
    calendar.timeZone = TimeZone(identifier: "UTC")!
    let dateFrom = calendar.startOfDay(for: date)
    let dateTo = calendar.date(byAdding: .day, value: 1, to: dateFrom)
    
    // Set predicate as date being compliant with date
    let fromPredicate = NSPredicate(format: "%@ >= %@", date as NSDate, dateFrom as NSDate)
    let toPredicate = NSPredicate(format: "%@ < %@", date as NSDate, dateTo! as NSDate)
    let datePredicate = NSCompoundPredicate(andPredicateWithSubpredicates: [fromPredicate, toPredicate])

    // CoreData API's to list only today places
    let fetchRequest: NSFetchRequest<Places> = Places.fetchRequest()
    fetchRequest.predicate = datePredicate
    if let context = (UIApplication.shared.delegate as? AppDelegate)?
        .persistentContainer.viewContext {
      let sort = NSSortDescriptor(key: #keyPath(Places.timestamp), ascending: false)
      fetchRequest.sortDescriptors = [sort]
      if let placesCoreData = try?
          context.fetch(fetchRequest) {
        // Store it to the cache
        print(placesCoreData.count)
      }
    }
  }

Upvotes: 0

Views: 99

Answers (1)

Larme
Larme

Reputation: 26036

Your predicate are wrong.

let fromPredicate = NSPredicate(format: "%@ >= %@", date as NSDate, dateFrom as NSDate)
let toPredicate = NSPredicate(format: "%@ < %@", date as NSDate, dateTo! as NSDate)
let datePredicate = NSCompoundPredicate(andPredicateWithSubpredicates: [fromPredicate, toPredicate])

You aren't testing it against the properties of Places. Currently, it's equivalent to NSPredicate(value: true), because date is greater or equal to dateFrom and less that dateTo. It should always be true (according to how values are created). That's why you are getting all the places when fetching.

It should be:

let fromPredicate = NSPredicate(format: "%K >= %@", argumentArray: [#keyPath(Places.dateVariableName), dateFrom]
let toPredicate = NSPredicate(format: "%K < %@", argumentArray: [#keyPath(Places.dateVariableName), dateTo]

Upvotes: 1

Related Questions