UPDATED - CODE WITH SOLUTION BELOW
I have used CoreData on a number of different projects without issue but this one has me stumped. The only difference between this and previous projects is I am using CloudKit.
All I am trying to do is set a value for a current record. I have an entity called Folders and in that entity is an attribute named folderPosition which is an Int16.
My code to update the value looks like this:
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")
}
}
However I keep getting the following error:
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>
The other strange thing is, I have an attribute called folderName (String), if I update with the same code I get no crashes and I can see that it iterates through all the folders available in CoreData and updates the value for folderName but then when I fetch the data back, the folder names have not changed. It's all very odd.
Updated Code Based on Helpful Comments and Answers - Thank You!
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)
}
}
First of all and unrelated to the issue the logic to reindex the position looks pretty weird. Actually you have to decrement the index only from the item at position deleted position + 1.
As mentioned in the comments the error is caused by a typo. You mean
items.setValue(items.folderPosition - 1, forKey: "folderPosition")
instead of
managedObjectContext.setValue(items.folderPosition - 1, forKey: "folderPosition")
There are many bad practices in the code.
Folder
and for item in ...
.folderPosition
to position
NSFetchRequest<Folders>
.count == 0
. There is isEmpty
.catch
blocks. Print the 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)
}
}
To reindex the entire data set starting at 0 there is a smarter way:
for (index, folder) in folders.enumerated() {
folder.folderPosition = index
}