Bool 谓词导致零行计数
Bool predicate causes zero rows count
当我尝试执行 CoreData 获取请求时,我得到了正确的行数。
let req = Track.fetchRequest()
return try context.count(for: req)
// result: 81
有效:
当我尝试添加 bool 条件时,
let req = Track.fetchRequest()
req.predicate = NSPredicate(format: "isSentToServer = NO")
return try context.count(for: req)
// result: 0
没有。结果总是 0(但它仍然应该是 81)无论我尝试什么:
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")
注意:isSentToServer
是一个正确识别的属性,更改大小写或添加 Z
都无济于事。
是否有大量 Swift 教程作者不知道的更改?
编辑:Track
class 由核心模型实体编辑器自动生成,isSentToServer 数据类型为 Bool
(编辑器中为 "Boolean")(不是 Bool?
)
更新
这是我的测试代码的输出,按照建议 -com.apple.CoreData.SQLDebug 1
(谓词: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
对于 = NO
和其他 "equal" 情况,它生成 SQL "= ?"
而不是
如何创建 Track
对象?
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
编辑 2:请注意,我已经在我的 Xcode 中尝试了 "Erase data" 的 iPhone 6 模拟器,并重新创建了我的 Track 对象,仍然是第二个请求 returns 零行计数。
Xcode:版本 10.2 (10E125)
目标 iOS SDK/version:11.0 或 12.2,无差异
$ xcodebuild -showsdks
iOS SDKs:
iOS 12.2 -sdk iphoneos12.2
iOS Simulator SDKs:
Simulator - iOS 12.2 -sdk iphonesimulator12.2
这是解决方法的评论。
有用的是以下组合:
- 为新对象设置
track.isSentToServer = false
显式
- set
track.time = Date()
for new objects excplicitly(我不在谓词中使用这个字段)(生成的类型是: Date?
)
因此,谓词有效。
不过,我的期望很合乎逻辑:
false
必须是默认值,因为它具有 Bool
类型(而不是 Bool?
)。
nil
必须是 Date?
属性的默认值,并且不能影响未提及它的谓词。
我无法找到有关此行为是否已记录的信息。
当我尝试执行 CoreData 获取请求时,我得到了正确的行数。
let req = Track.fetchRequest()
return try context.count(for: req)
// result: 81
有效:
当我尝试添加 bool 条件时,
let req = Track.fetchRequest()
req.predicate = NSPredicate(format: "isSentToServer = NO")
return try context.count(for: req)
// result: 0
没有。结果总是 0(但它仍然应该是 81)无论我尝试什么:
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")
注意:isSentToServer
是一个正确识别的属性,更改大小写或添加 Z
都无济于事。
是否有大量 Swift 教程作者不知道的更改?
编辑:Track
class 由核心模型实体编辑器自动生成,isSentToServer 数据类型为 Bool
(编辑器中为 "Boolean")(不是 Bool?
)
更新
这是我的测试代码的输出,按照建议 -com.apple.CoreData.SQLDebug 1
(谓词: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
对于 = NO
和其他 "equal" 情况,它生成 SQL "= ?"
而不是
如何创建 Track
对象?
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
编辑 2:请注意,我已经在我的 Xcode 中尝试了 "Erase data" 的 iPhone 6 模拟器,并重新创建了我的 Track 对象,仍然是第二个请求 returns 零行计数。
Xcode:版本 10.2 (10E125)
目标 iOS SDK/version:11.0 或 12.2,无差异
$ xcodebuild -showsdks
iOS SDKs:
iOS 12.2 -sdk iphoneos12.2
iOS Simulator SDKs:
Simulator - iOS 12.2 -sdk iphonesimulator12.2
这是解决方法的评论。
有用的是以下组合:
- 为新对象设置
track.isSentToServer = false
显式 - set
track.time = Date()
for new objects excplicitly(我不在谓词中使用这个字段)(生成的类型是:Date?
)
因此,谓词有效。
不过,我的期望很合乎逻辑:
false
必须是默认值,因为它具有Bool
类型(而不是Bool?
)。nil
必须是Date?
属性的默认值,并且不能影响未提及它的谓词。
我无法找到有关此行为是否已记录的信息。