创建NSPredicate实例触发EXC_BAD_ACCESS,升级Xcode后崩溃原因咨询
问题原因与解决方案
这个问题我在升级Swift 4.1的时候也踩过坑,本质是Swift 4.1对Bool类型与CVarArg的桥接逻辑做了调整,导致原来的隐式转换不再生效。
为什么旧版本正常,新版本崩溃?
在Xcode 9.2(Swift 4.0)中,Swift会自动把Bool值隐式包装成NSNumber再转成CVarArg,Core Data的NSPredicate能正确识别这个值。但升级到Swift 4.1后,这个隐式桥接被移除了,你直接写true as CVarArg其实传递的是一个无效的指针(因为Bool是值类型,不是对象),所以触发了EXC_BAD_ACCESS内存访问错误。
几种可行的修复方案
方案一:显式包装成NSNumber
这是最稳妥的写法,直接给%@格式符传递NSNumber类型的布尔值:request.predicate = NSPredicate(format: "saved = %@", NSNumber(value: true))方案二:使用%d格式符
因为Swift的Bool可以桥接到Int(true对应1,false对应0),所以可以用%d格式符直接传递布尔值:request.predicate = NSPredicate(format: "saved = %d", true)方案三:使用谓词闭包语法(Swift 3+)
这种写法类型更安全,不需要关心格式符的问题:request.predicate = NSPredicate { object in return object.value(forKey: "saved") as? Bool == true } // 或者更简洁的写法 request.predicate = NSPredicate { $0["saved"] as? Bool == true }
建议优先用方案三或者方案一,类型安全性更高,能避免类似的版本兼容问题。
内容的提问来源于stack exchange,提问作者Whirlwind
相关产品推荐
相关产品推荐

