通过对象的枚举属性使用 NSPredicate 获取核心数据管理对象的问题
Issue with fetching Core Data managed object using NSPredicate by object's enum attribute
我在获取具有 enum
属性和 Int16
rawValues 的核心数据托管对象时遇到问题。程序在调用 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
}
崩溃信息是:
Thread 1: EXC_BAD_ACCESS (code=1, address=0x3)
当我将第 3 行更改为以下内容时,出现另一种错误。
这是备用代码:
fetchRequest.predicate = NSPredicate(format: "%K = %@", #keyPath(Book.bookType), bookType as! CVarArg)
这是替代代码导致的错误:
Thread 1: signal SIGABRT
我在调试输出中看到了这个:
Could not cast value of type 'ProjectName.BookType' (0x10ac10098)
to '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
属性从我的核心数据存储中正确获取 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马上投诉:
Argument type 'BookType' does not conform to expected type 'CVarArg'
如果我改用 bookType.rawValue
,XCode 就会停止抱怨。但是,程序在运行时崩溃并出现与上述相同的错误(第一个)。
更新二:
我已经应用了社区建议的 的答案。更具体地说,我已经尝试了使用 %i
或 @ld
而不是 %@
的问题答案中的建议,如下所示:
fetchRequest.predicate = NSPredicate(format: "bookTypeValue == %i", bookType.rawValue)
我已经尝试了另一个建议,它使用字符串插值,如下所示:
fetchRequest.predicate = NSPredicate(format: "bookTypeValue == %@", "\(bookType.rawValue)")
这些代码更改防止了崩溃,但是 func returnBook
returns nil,即使我确定数据在那里。由于某种原因获取或比较失败...
在为这个问题苦苦挣扎了好几个小时之后,我终于设法解决了它。
以下是我为解决问题所做的工作(按时间顺序排列):
- 我已经将
bookTypeValue
的类型从 Int16
更改为 Int32
,因为我在官方(存档)中看不到 16 位整数的格式说明符 documentation。我已经测试过,我可以确认,如果您在此处使用 %@
而不是正确的格式说明符(对于带符号的 32 位整数是 %d
),您会得到问题中的第一个错误:
Thread 1: EXC_BAD_ACCESS (code=1, address=0x3)
我已将 NSPredicate(format:)
调用更改为:
fetchRequest.predicate = NSPredicate(格式: "bookTypeValue == %d", bookType.rawValue)
我在 returnBook
函数中更改了第 5 行,如下所示:
do {
let results = try coreDataStack.managedContext.fetch(fetchRequest)
if results.count > 0 {
book = results.first
return book
}
} catch let error as NSError {
print("Fetch error: \(error) description: \(error.userInfo)")
}
我在获取具有 enum
属性和 Int16
rawValues 的核心数据托管对象时遇到问题。程序在调用 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
}
崩溃信息是:
Thread 1: EXC_BAD_ACCESS (code=1, address=0x3)
当我将第 3 行更改为以下内容时,出现另一种错误。
这是备用代码:
fetchRequest.predicate = NSPredicate(format: "%K = %@", #keyPath(Book.bookType), bookType as! CVarArg)
这是替代代码导致的错误:
Thread 1: signal SIGABRT
我在调试输出中看到了这个:
Could not cast value of type 'ProjectName.BookType' (0x10ac10098) to '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
属性从我的核心数据存储中正确获取 Book
对象,该属性位于 @objc enum
键入 Int16
rawValues?
更新:
我已经按照 Jesse Squires in a presentation 的建议尝试了其他方法:
- 从
enum
的定义 中删除了 - 使用
private
和public
属性访问enum
的实例...
@objc
关键字
我已经按照链接演示文稿中的建议更改了我的代码,并且我已经将 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马上投诉:
如果我改用Argument type 'BookType' does not conform to expected type 'CVarArg'
bookType.rawValue
,XCode 就会停止抱怨。但是,程序在运行时崩溃并出现与上述相同的错误(第一个)。
更新二:
我已经应用了社区建议的 %i
或 @ld
而不是 %@
的问题答案中的建议,如下所示:
fetchRequest.predicate = NSPredicate(format: "bookTypeValue == %i", bookType.rawValue)
我已经尝试了另一个建议,它使用字符串插值,如下所示:
fetchRequest.predicate = NSPredicate(format: "bookTypeValue == %@", "\(bookType.rawValue)")
这些代码更改防止了崩溃,但是 func returnBook
returns nil,即使我确定数据在那里。由于某种原因获取或比较失败...
在为这个问题苦苦挣扎了好几个小时之后,我终于设法解决了它。
以下是我为解决问题所做的工作(按时间顺序排列):
- 我已经将
bookTypeValue
的类型从Int16
更改为Int32
,因为我在官方(存档)中看不到 16 位整数的格式说明符 documentation。我已经测试过,我可以确认,如果您在此处使用%@
而不是正确的格式说明符(对于带符号的 32 位整数是%d
),您会得到问题中的第一个错误:
Thread 1: EXC_BAD_ACCESS (code=1, address=0x3)
我已将
NSPredicate(format:)
调用更改为:fetchRequest.predicate = NSPredicate(格式: "bookTypeValue == %d", bookType.rawValue)
我在
returnBook
函数中更改了第 5 行,如下所示:do { let results = try coreDataStack.managedContext.fetch(fetchRequest) if results.count > 0 { book = results.first return book } } catch let error as NSError { print("Fetch error: \(error) description: \(error.userInfo)") }