When i try to execute CoreData fetch request, i get correct number of rows.

let req = Track.fetchRequest()
return try context.count(for: req)

// result: 81

It works:

SQLite browser request

When i try to add bool condition,

let req = Track.fetchRequest()
req.predicate = NSPredicate(format: "isSentToServer = NO")
return try context.count(for: req)

// result: 0

it doesn't. Result it always 0 (but it still should be 81) whatever i try:

NSPredicate(format: "isSentToServer = %i", NSNumber(value: false))
NSPredicate(format: "isSentToServer = %@", NSNumber(value: false))
NSPredicate(format: "isSentToServer = 0")
NSPredicate(format: "isSentToServer = %@", false)
NSPredicate(format: "isSentToServer = %@", 0)
NSPredicate(format: "isSentToServer != YES")
NSPredicate(format: "isSentToServer == NO")
NSPredicate(format: "isSentToServer == %@", "NO")

NOTE: isSentToServer is a correctly recognized attribute, changing case or adding Z won't help.

Are there any changes tons of Swift Tutorial authors are unaware of?

EDIT: Track class is auto-generated by Core Model entity editor, and its type is Bool ("Boolean" in editor) (not Bool?)

UPDATE

Here is output from my test code with -com.apple.CoreData.SQLDebug 1 as suggested (predicate: isSentToServer != YES):

CoreData: sql: SELECT TBL_NAME FROM SQLITE_MASTER WHERE TBL_NAME = 'Z_METADATA'
CoreData: sql: pragma recursive_triggers=1
CoreData: sql: pragma journal_mode=wal
CoreData: sql: SELECT Z_VERSION, Z_UUID, Z_PLIST FROM Z_METADATA
CoreData: sql: SELECT TBL_NAME FROM SQLITE_MASTER WHERE TBL_NAME = 'Z_METADATA'
CoreData: sql: SELECT TBL_NAME FROM SQLITE_MASTER WHERE TBL_NAME = 'Z_MODELCACHE'
CoreData: sql: SELECT TBL_NAME FROM SQLITE_MASTER WHERE TBL_NAME = 'ACHANGE'
CoreData: sql: SELECT COUNT(*) FROM ZTRACK
CoreData: annotation: total count request execution time: 0.0004s for count of 90.
Total track objects: 90
CoreData: sql: SELECT COUNT( DISTINCT t0.Z_PK) FROM ZTRACK t0 WHERE  t0.ZISSENTTOSERVER <> ? 
CoreData: annotation: total count request execution time: 0.0005s for count of 0.
Track objects pending upload: 0

For = NO and other "equal" cases it generates SQL "= ?" instead

How do i create Track objects?

let track = Track(context: context) // context is from AppDelegate, auto-generated by Xcode
// set up some properties
// not assigning any isSentToServer value explicitly
context.save() // no errors

EDIT 2: Note, i've tried "Erase data" of iPhone 6 simulator in my Xcode, and re-created my Track objects, still the second request returns zero rows count.

Xcode: Version 10.2 (10E125)

Targeting iOS SDK/version: 11.0 or 12.2, no difference

$ xcodebuild -showsdks
iOS SDKs:
    iOS 12.2                        -sdk iphoneos12.2

iOS Simulator SDKs:
    Simulator - iOS 12.2            -sdk iphonesimulator12.2

1 Answers

0
Samantha On

This is a comment with workaround.

What helped, is combination of:

  1. set track.isSentToServer = false for new objects explicitly
  2. set track.time = Date() for new objects excplicitly (i do not use this field in predicate) (generated type is: Date?)

As a result, predicate works.

Although, my expectations were pretty logic:

  1. false must be default as it has Bool type (not Bool?).
  2. nil must be default value for Date? attribute and it must not affect predicates that don't mention it.

I was not able to find information is this behavior is documented or not.