【发布时间】:2020-02-09 23:40:36
【问题描述】:
我在获取具有enum 属性和Int16 rawValues 的Core Data 托管对象时遇到问题。调用NSPredicate(format:)时程序崩溃。
这是导致崩溃的代码(第 3 行):
func returnBook (bookType: BookType) -> Book? {
let fetchRequest = NSFetchRequest<Book>(entityName: "Book")
fetchRequest.predicate = NSPredicate(format: "%K = %@", #keyPath(Book.bookType), bookType.rawValue as CVarArg)
fetchRequest.fetchLimit = 1
let book = (try? fetchRequest.execute())?.first
return book
}
崩溃消息是:
线程 1:EXC_BAD_ACCESS(代码=1,地址=0x3)
当我用以下内容更改第 3 行时,我得到了另一种错误。
这是替代代码:
fetchRequest.predicate = NSPredicate(format: "%K = %@", #keyPath(Book.bookType), bookType as! CVarArg)
这是替代代码导致的错误:
线程 1:信号 SIGABRT
我在调试输出中看到了这一点:
无法转换类型“ProjectName.BookType”的值 (0x10ac10098) 到 'Swift.CVarArg' (0x10b698548)。
以下是项目中的一些其他相关代码:
@objc(Book)
public class Book: NSManagedObject {
// …
}
extension Book {
@NSManaged public var bookType: BookType
}
@objc public enum BookType: Int16 {
case fiction = 0
case nonFiction = 1
case reference = 2
}
我的问题:如何使用 bookType 属性从我的 Core Data 存储中正确获取 Book 对象,该属性位于 @objc enum 类型和 Int16 rawValues 中?
更新:
我已经按照 Jesse Squires 的建议 in a presentation 尝试了其他方法:
- 从
enum的定义中删除了@objc关键字 - 使用
private和public属性访问enum的实例...
我已按照链接演示文稿中的建议更改了我的代码,并将 Core Data 的“.xcdatamodeld”文件中的bookType 属性名称更改为bookTypeValue。
extension Book {
public var bookType: BookType {
get {
return BookType(rawValue: self.bookTypeValue)!
}
set {
self.bookTypeValue = newValue.rawValue
}
}
@NSManaged private var bookTypeValue: Int16
}
public enum BookType: Int16 {
case fiction = 0
case nonFiction = 1
case reference = 2
}
我尝试使用上面链接的演示文稿中建议的私有值来获取...:
fetchRequest.predicate = NSPredicate(format: "bookTypeValue == %@", bookType)
但是我也无法用这种方法解决我的问题...... XCode 立即抱怨:
参数类型“BookType”不符合预期的类型“CVarArg”
如果我改用bookType.rawValue,XCode 就会停止抱怨。但是,程序在运行时崩溃并出现上述相同的错误(第一个)。
更新 2:
我已将社区建议的答案应用到this question。更具体地说,我已经尝试了使用%i 或@ld 而不是%@ 的问题答案中的建议,如下所示:
fetchRequest.predicate = NSPredicate(format: "bookTypeValue == %i", bookType.rawValue)
我尝试了另一个使用字符串插值的建议,如下所示:
fetchRequest.predicate = NSPredicate(format: "bookTypeValue == %@", "\(bookType.rawValue)")
这些代码更改防止了崩溃,但 func returnBook 返回 nil,即使我确定数据在那里。由于某种原因,获取或比较失败...
【问题讨论】:
-
我猜bookType必须在模型编辑器中定义为Transformable?当你把它重命名为 bookTypeValue 时,你是不是把它改成了 Integer?谓词不适用于可转换属性(至少在获取时不行)。
-
@pbasdf bookType 在模型编辑器中被定义为 Int16(这里建议:stackoverflow.com/a/31681870/3780985),在我将它重命名为 bookTypeValue 后,它在模型编辑器中仍然与 Int16 相同。我只是将代码中的类型从 BookType 更改为 Int16。
标签: swift core-data enums nspredicate