NSArray element failed to match the Swift Array Element type when subscripting

I’ve got the following CoreData query in Swift 5.8. The compiler sees the type of vals as [Value]. vals.count == 1. When I try to get the first element, the app crashes with “Fatal error: NSArray element failed to match the Swift Array Element type. Expected Value but found NSManagedObject”

let req = NSFetchRequest<Value>(entityName: "Value")
req.predicate = NSPredicate(format: "name == %@", inKey)

let moc = Model.shared.container.viewContext
let vals = try moc.fetch(req)
if vals.count == 1
{
	let v = vals[0]   //  Error here
	return v.value
}
class Value : NSManagedObject {
	@NSManaged	var	name			:	String
	@NSManaged	var	value			:	String
}

If I print the description of vals in the debugger, I get:

Printing description of vals:
([MissionClock.Value]) vals = 1 value {
  [0] = 0x0000600000f782d0
}
Fatal error: NSArray element failed to match the Swift Array Element type
Expected Value but found NSManagedObject

Oh and btw, if I try to create the fetch request like this (as shown here) I get an error:

let req: NSFetchRequest<Value> = Value.fetchRequest()
Cannot assign value of type 'NSFetchRequest<any NSFetchRequestResult>' to type 'NSFetchRequest<Value>'

What’s going on here?

Update: I had some stuff set up incorreclty with Core Data, and once I sorted it out, everything worked. Everything doesn’t quite make sense, but the questions are all Core Data-related and not really Swift.

I had defined the Value class in Swift, but the fetchRequest() method wasn’t creating the right thing because I had forgotten to specify the class in the XCDataModel. After wasting time defining it in Objective-C (I thought I was doing something wrong in Swift), I finally realized I needed to specify the app’s module name when defining it in Swift (but not Obj-C). What’s still perplexing is that I have to cast the result of Value.fetchRequest() as! NSFetchRequest<Value>, even though the example I found online doesn’t. Seems the Swift interface could’ve been written to return the non-generic type.

2 Likes

Just to help future readers - I got this same issue when converting an Objective-C ManagedObject subclass to Swift. The solution is to add a new model version and add the app name into the MOC editor "Module" field for each object. Took me a long time to get there.

I assume will create a light-weight migration as I assume any change to the schema modifies its version number, but frankly I just don't know for sure.