CoreData:此 class 不符合键 folderPosition 的键值编码

CoreData: this class is not key value coding-compliant for the key folderPosition

已更新 - 具有以下解决方案的代码

我已经在许多不同的项目中使用了 CoreData,没有出现任何问题,但是这个让我很困惑。这个项目和之前项目的唯一区别是我使用的是 CloudKit.

我只想为当前记录设置一个值。我有一个名为 Folders 的实体,在该实体中有一个名为 folderPosition 的 Int16 属性。

我更新值的代码如下所示:

static func updateFolderPositionsAfterFolderDeletion(managedObjectContext: NSManagedObjectContext = AppDelegate.viewContext) {
    
    let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Folders")
    let sortDescriptor = NSSortDescriptor(key: "folderPosition", ascending: true)
    fetchRequest.sortDescriptors = [sortDescriptor]
    do {
        if let fetchResults = try managedObjectContext.fetch(fetchRequest) as? [Folders] {
            if fetchResults.count != 0 {
                for items in fetchResults {
                   managedObjectContext.setValue(items.folderPosition - 1, forKey: "folderPosition")
                }
            }
        }
        try? managedObjectContext.save()
    }
    catch {
        print("Catch")
    }
}

但是我不断收到以下错误:

quotelibc++abi.dylib: terminating with uncaught exception of type NSException *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<NSManagedObjectContext 0x600001cb4c30> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key folderPosition.' terminating with uncaught exception of type NSExceptionquote>

另一个奇怪的事情是,我有一个名为 folderName (String) 的属性,如果我使用相同的代码进行更新,我不会崩溃,而且我可以看到它遍历了 CoreData 中所有可用的文件夹并更新了值对于 folderName 但是当我取回数据时,文件夹名称没有改变。一切都很奇怪。

根据有用的评论和回答更新了代码 - 谢谢!

static func updateFolderPositionsAfterFolderDeletion(managedObjectContext: NSManagedObjectContext = AppDelegate.viewContext) {
    
    let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Folders")
    let sortDescriptor = NSSortDescriptor(key: "folderPosition", ascending: true)
    fetchRequest.sortDescriptors = [sortDescriptor]
    do {
        if let fetchResults = try managedObjectContext.fetch(fetchRequest) as? [Folders] {
            for (index, folder) in fetchResults.enumerated() {
                folder.folderPosition = (Int16(index))
            }
        }
        try? managedObjectContext.save()
    }
    catch {
        print(error)
    }
}

首先,与问题无关的是,重新索引位置的逻辑看起来很奇怪。实际上你只需要从位置 deleted position + 1.

处的项目减少索引

如评论中所述,错误是由错字引起的。你是说

items.setValue(items.folderPosition - 1, forKey: "folderPosition")

而不是

managedObjectContext.setValue(items.folderPosition - 1, forKey: "folderPosition")

代码中有很多不好的做法。

  • 命名混乱。以单数形式命名实体和循环元素:Folderfor item in ....
  • 避免冗余信息。将 folderPosition 重命名为 position
  • 比 KVC 更喜欢点符号。
  • 利用通用提取请求:NSFetchRequest<Folders>
  • 切勿使用 count == 0 检查空字符串或空数组。有isEmpty.
  • 空支票无论如何都是多余的。如果数组为空,则跳过循环。
  • 永远不要在 catch 块中打印无意义的文字字符串。打印 error.

static func updateFolderPositionsAfterFolderDeletion(managedObjectContext: NSManagedObjectContext = AppDelegate.viewContext) {
    
    let fetchRequest = NSFetchRequest<Folders>(entityName: "Folders")
    let sortDescriptor = NSSortDescriptor(key: "folderPosition", ascending: true)
    fetchRequest.sortDescriptors = [sortDescriptor]
    do {
        let folders = try managedObjectContext.fetch(fetchRequest)
        for folder in folders {
           folder.folderPosition = folder.folderPosition - 1
        }
        try managedObjectContext.save()
    }
    catch {
        print(error)
    }
}

要重新索引从 0 开始的整个数据集,有一种更聪明的方法:

for (index, folder) in folders.enumerated() {
    folder.folderPosition = index
}