Cannot convert value of type 'NSFetchRequest<NSFetchRequestResult>' to specified type 'NSFetchRequest<T>'
Asked Answered
M

4

19

I want to use new Core Data API introduced in iOS10.

@available(iOS 10.0, *)
open class func fetchRequest() -> NSFetchRequest<NSFetchRequestResult>

I created generic function to fetching all kinds of objects:

func getAllEntities<T: NSManagedObject>(ofType type: T.Type, success: @escaping ([T]) -> ()) throws -> [T] {
    let fetchRequest: NSFetchRequest<T> = T.fetchRequest()
    let asyncFetchRequest = NSAsynchronousFetchResult(fetchRequest: fetchRequest) { result in
        success(result.finalResult ?? [])
    }

    try databaseStack.persistentContainer.viewContext.execute(asyncFetchRequest)
}

but in line let fetchRequest: NSFetchRequest<T> = T.fetchRequest() I got issue:

Cannot convert value of type 'NSFetchRequest<NSFetchRequestResult>' to specified type 'NSFetchRequest<T>'

What did I do wrong?

Muriel answered 5/1, 2018 at 14:37 Comment(1)
I have exacly the same problem. The strangest thing is that, I have one project where it's working like a charm, and another one with the error, same as you. Here: useyourloaf.com/blog/cleaning-up-core-data-fetch-requests is our solution described.Ullman
B
14

T.fetchRequest() returns a NSFetchRequest<NSFetchRequestResult>, you have to explicitly cast it to the specific NSFetchRequest<T>:

let fetchRequest = T.fetchRequest() as! NSFetchRequest<T>
let asyncFetchRequest = NSAsynchronousFetchRequest(fetchRequest: fetchRequest) { result in
    success(result.finalResult ?? [])
}
Bunion answered 5/1, 2018 at 18:24 Comment(1)
I had hope that I can skip force casting. I demanded from .fetchRequest() explicit type. Well, nothing. Tnx for your answer.Muriel
F
4

Try either one of these.

One: I experienced something similar in my project.

I found that there were problems with the auto generated headers of Core Data entities. Try deleting from:

/Users/**user**/Library/Developer/Xcode/DerivedData/**AppName**/Build/Intermediates/**AppName**/Debug-iphonesimulator/**AppName**.build/DerivedSources/CoreDataGenerated

then clean your project with command+shift+K

Then try building.

Two: Try using let fetchRequest = NSFetchRequest<T>(entityName: NSStringFromClass(T.self))

Swifty style of 2nd approach, works 100%:

let fetchRequest = NSFetchRequest<T>(entityName: String(describing: T.self))
Fowle answered 5/1, 2018 at 15:36 Comment(3)
I set in my data model Codegen as Manual/None so I don't have autogenerated code. Maybe is causes the problem?Muriel
Updated my answer againFowle
Second proposition is a workaround. I want to find why my solution doesn't work without using different API.Muriel
S
0

The NSFetchRequest boilerplate call (for array of information, for instance) ends with (); don't forget that or you might get an error of this type.

This is easy to miss especially if you type your code out instead of copy-pasting the boiler-plate code.

Saveloy answered 8/7, 2019 at 20:7 Comment(0)
P
0

Consider using this extension for ManagedObject, I've force unwrap entity.name and allowed it to crash if return nil.

    public static func fetchRequest() -> NSFetchRequest<Self> {
        return NSFetchRequest<Self>(entityName: Self.entityName)
    }
    
    public static var entity: NSEntityDescription { return entity()  }
    
    /// - important: If name return nil, check xcmodeld and Module config Current Product Module
    public static var entityName: String { return entity.name!  }
Papuan answered 24/2, 2024 at 10:18 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.