[英]Issue with fetching Core Data managed object using NSPredicate by object's enum attribute
I have an issue with fetching a Core Data managed object which has an enum
attribute with Int16
rawValues.我在获取具有
Int16
rawValues 的enum
属性的 Core Data 托管对象时遇到问题。 The program crashes when calling NSPredicate(format:)
.调用
NSPredicate(format:)
时程序崩溃。
This is the code (3rd line) that results a crash:这是导致崩溃的代码(第 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
}
Crash message is:崩溃消息是:
Thread 1: EXC_BAD_ACCESS (code=1, address=0x3)
线程 1:EXC_BAD_ACCESS(代码=1,地址=0x3)
When I change the 3rd line with the following, I get another kind of error.当我使用以下内容更改第 3 行时,出现另一种错误。
This is the alternative code:这是替代代码:
fetchRequest.predicate = NSPredicate(format: "%K = %@", #keyPath(Book.bookType), bookType as! CVarArg)
And this is the error resulted by that alternative code:这是该替代代码导致的错误:
Thread 1: signal SIGABRT
线程 1:信号 SIGABRT
And I see this in the debug output:我在调试输出中看到了这一点:
Could not cast value of type 'ProjectName.BookType' (0x10ac10098) to 'Swift.CVarArg' (0x10b698548).
无法将“ProjectName.BookType”(0x10ac10098)类型的值转换为“Swift.CVarArg”(0x10b698548)。
Here are some other related code in the Project:以下是项目中的其他一些相关代码:
@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
}
My question: How can I properly fetch the Book
object from my Core Data store by using its bookType
attribute, which is in an @objc enum
type with Int16
rawValues?我的问题:如何使用
bookType
属性从我的 Core Data 存储中正确获取Book
对象,该属性位于具有Int16
rawValues 的@objc enum
类型中?
Update:更新:
I have tried something else as suggested in a presentation by Jesse Squires:我已经按照 Jesse Squires 的演示文稿中的建议尝试了其他方法:
@objc
keyword from enum
's definitionenum
的定义中删除了@objc
关键字private
and public
properties to access the enum
's instances...private
和public
属性来访问enum
的实例... I have changed my code as suggested in the linked presentation, and I have changed the name of bookType
attribute in Core Data's ".xcdatamodeld" file to bookTypeValue
.我已按照链接演示文稿中的建议更改了代码,并将 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
}
And I tried to fetch using the private value as suggested in the presentation linked above...:我尝试使用上面链接的演示文稿中建议的私有值来获取...:
fetchRequest.predicate = NSPredicate(format: "bookTypeValue == %@", bookType)
However I could not solve my problem with this method either... XCode complains immediately:但是我也无法用这种方法解决我的问题...... XCode 立即抱怨:
Argument type 'BookType' does not conform to expected type 'CVarArg'
参数类型“BookType”不符合预期类型“CVarArg”
XCode stops complaining if I use bookType.rawValue
instead.如果我改用
bookType.rawValue
XCode 就会停止抱怨。 However, program crashes during runtime with the same error above (first one).但是,程序在运行时崩溃并出现上述相同的错误(第一个)。
Update 2:更新 2:
I have applied the answers given to this question which is suggested by the community.我已经应用了社区建议的这个问题的答案。 To be more specific, I have tried the suggestion in the answer to that question which is using
%i
, or @ld
instead of %@
like so:更具体地说,我在使用
%i
或@ld
而不是%@
问题的答案中尝试了建议,如下所示:
fetchRequest.predicate = NSPredicate(format: "bookTypeValue == %i", bookType.rawValue)
and I have tried the other suggestion which is using String interpolation like so:我已经尝试了另一个使用字符串插值的建议,如下所示:
fetchRequest.predicate = NSPredicate(format: "bookTypeValue == %@", "\(bookType.rawValue)")
These code changes prevented crashes, but func returnBook
returns nil, even if I am sure that the data is there.这些代码更改防止了崩溃,但 func
returnBook
返回 nil,即使我确定数据在那里。 Fetch or comparison fails for some reason...由于某种原因,获取或比较失败...
After struggling with this problem for many hours finally I have managed to solve it.在为这个问题苦苦挣扎了几个小时后,我终于设法解决了它。
Here is what I have done to solve the problem in chronological order:以下是我为按时间顺序解决问题所做的工作:
bookTypeValue
from Int16
to Int32
, because I could not see a format specifier for 16-bit integers in the official (archived) documentation .bookTypeValue
的类型从Int16
更改为Int32
,因为我在官方(存档) 文档中看不到 16 位整数的格式说明符。 I have tested and I can confirm that if you use %@
here instead of correct format specifier, which is %d
for signed 32-bit integers, you get the first error in the question:%@
而不是正确的格式说明符(对于有符号 32 位整数是%d
,您会得到问题中的第一个错误:Thread 1: EXC_BAD_ACCESS (code=1, address=0x3)
线程 1:EXC_BAD_ACCESS(代码=1,地址=0x3)
I have changed the NSPredicate(format:)
call like so:我已经更改了
NSPredicate(format:)
调用,如下所示:
fetchRequest.predicate = NSPredicate(format: "bookTypeValue == %d", bookType.rawValue) fetchRequest.predicate = NSPredicate(格式:"bookTypeValue == %d", bookType.rawValue)
I have changed the 5th line in returnBook
func like so:我已经更改了
returnBook
func 中的第 5 行, returnBook
所示:
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)") }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.