繁体   English   中英

使用 NSPredicate 通过对象的枚举属性获取核心数据托管对象的问题

[英]Issue with fetching Core Data managed object using NSPredicate by object's enum attribute

我在获取具有Int16 rawValues 的enum属性的 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对象,该属性位于具有Int16 rawValues 的@objc enum类型中?

更新:

我已经按照 Jesse Squires 的演示文稿中的建议尝试了其他方法:

  1. enum的定义中删除了@objc关键字
  2. 使用privatepublic属性来访问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:

我已经应用了社区建议的这个问题的答案。 更具体地说,我在使用%i@ld而不是%@问题的答案中尝试了建议,如下所示:

fetchRequest.predicate = NSPredicate(format: "bookTypeValue == %i", bookType.rawValue)

我已经尝试了另一个使用字符串插值的建议,如下所示:

fetchRequest.predicate = NSPredicate(format: "bookTypeValue == %@", "\(bookType.rawValue)")

这些代码更改防止了崩溃,但 func returnBook返回 nil,即使我确定数据在那里。 由于某种原因,获取或比较失败...

在为这个问题苦苦挣扎了几个小时后,我终于设法解决了它。

以下是我为按时间顺序解决问题所做的工作:

  1. 我已将bookTypeValue的类型从Int16更改为Int32 ,因为我在官方(存档) 文档中看不到 16 位整数的格式说明符。 我已经测试过,我可以确认,如果您在此处使用%@而不是正确的格式说明符(对于有符号 32 位整数是%d ,您会得到问题中的第一个错误:

线程 1:EXC_BAD_ACCESS(代码=1,地址=0x3)

  1. 我已经更改了NSPredicate(format:)调用,如下所示:

    fetchRequest.predicate = NSPredicate(格式:"bookTypeValue == %d", bookType.rawValue)

  2. 我已经更改了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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM