布尔谓词导致零行数
Posted
技术标签:
【中文标题】布尔谓词导致零行数【英文标题】:Bool predicate causes zero rows count 【发布时间】:2019-04-21 20:18:22 【问题描述】:当我尝试执行 CoreData 获取请求时,我得到了正确的行数。
let req = Track.fetchRequest()
return try context.count(for: req)
// result: 81
有效:
当我尝试添加布尔条件时,
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
类由 Core Model 实体编辑器自动生成,isSentToServer 数据类型为Bool
(编辑器中的“布尔”)(不是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
和其他“相等”的情况,它会生成 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 中尝试过 iPhone 6 模拟器的“擦除数据”,并重新创建了我的 Track 对象,但第二个请求仍然返回零行数。
Xcode:版本 10.2 (10E125)
针对 ios SDK/版本:11.0 或 12.2,没有区别
$ xcodebuild -showsdks
iOS SDKs:
iOS 12.2 -sdk iphoneos12.2
iOS Simulator SDKs:
Simulator - iOS 12.2 -sdk iphonesimulator12.2
【问题讨论】:
谓词编程指南指出,对于布尔值,您应该使用类似"someAttribute == YES"
的东西。我在您的列表中没有看到的一件事是"isSentToServer == NO"
。试试看。
"isSentToServer = NO"
应该适用于布尔属性(=
和 ==
在谓词中被同等对待)。
为了完整起见,更新您的问题,显示实体声明,清楚地显示isSentToServer
属性是如何声明的。
我在模拟器中的 iOS 应用程序显示第二个请求的结果 0,我敢肯定。我试图交换请求的顺序(有和没有谓词),但这没有区别。我从viewWillAppear()
提出这些请求,并通过print()
进行报告。我使用相同的上下文,但每次调用都使用新的 FetchRequest。
激活核心数据调试(启动参数-com.apple.CoreData.SQLDebug 3
,参见developer.apple.com/library/archive/documentation/Cocoa/…)并检查输出。
【参考方案1】:
这是一个带有解决方法的评论。
有帮助的是以下组合:
-
为新对象显式设置
track.isSentToServer = false
为新对象明确设置track.time = Date()
(我不在谓词中使用此字段)(生成类型为:Date?
)
因此,谓词有效。
虽然,我的期望很符合逻辑:
false
必须是默认值,因为它具有 Bool
类型(不是 Bool?
)。
nil
必须是 Date?
属性的默认值,并且不得影响未提及它的谓词。
我无法找到有关此行为是否记录在案的信息。
【讨论】:
根据我的经验,布尔属性可以具有三个值:true、false 和 null。提取谓词和过滤谓词以不同方式处理空值。解决方案:始终为数据模型中的布尔属性设置默认值。 请问有什么经验?我看到你在苹果上的代码,我只是从来没有见过布尔值有三个可能的值,尤其是在 SQL 中。仅适用于特定框架中的可空值,例如 Swift 或 C# 中的bool?
,但我在自动生成的实体类中有 bool
。在 SQL/SQLite 中,bool 字段是 tinyint 或 integer,0 被认为是 false,而不是 null AFAIK?
可选布尔属性的值可以是nil
。数据模型中的默认默认值为 None。以上是关于布尔谓词导致零行数的主要内容,如果未能解决你的问题,请参考以下文章