簡體   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