I'm using core data in a project and it breaks on fetch...on iOS 8, but not on any other iOS version. The error I'm getting is:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'keypath myId not found in entity <NSSQLEntity Entity id=1>'
I don't understand this at all, the myId has always been there and it works fine with iOS 9 and 10.I've tried removing the app and installing it again, but to no avail. It happens on both the simulator and on device.
This is my code executing the fetch
static func fetch(_ sortDescriptors: [NSSortDescriptor]?, predicate: NSPredicate?, entityName: String) -> [NSManagedObject] {
let managedObjectContext = (UIApplication.shared.delegate as! AppDelegate).managedObjectContext
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: entityName)
fetchRequest.sortDescriptors = sortDescriptors
fetchRequest.predicate = predicate
var fetchedObjects = [NSManagedObject]()
do {
fetchedObjects = try managedObjectContext.fetch(fetchRequest) as! [NSManagedObject]
} catch {
log.error("error")
}
return fetchedObjects
}
It breaks inside the do-statement and doesn't throw an error. On iOS 9.0+ it doesn't throw any errors either. The code is written using Swift 3.
Related
The Scenario
I'm using Core Data inside my main app and my widget.
To share my Persistent Container I use this custom stack that targets both my app and my widget and its working fine
class CoreDataService {
static let shared = CoreDataService()
lazy var context: NSManagedObjectContext = persistentContainer.viewContext
lazy var persistentContainer: NSPersistentCloudKitContainer = {
let container = NSPersistentCloudKitContainer(name: "my.app.name")
let storeURL = URL.storeURL(for: "my.app.group", databaseName: "my.app.name")
let storeDescription = NSPersistentStoreDescription(url: storeURL)
container.persistentStoreDescriptions = [storeDescription]
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
return container
}()
func saveContext () {
let context = self.context
if context.hasChanges {
do {
try context.save()
} catch {
let nserror = error as NSError
fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
}
}
}
}
The Problem
But when I access my widget from the home and I tap it to go to the app, whenever I use #FetchRequest in my code I get this error
CoreData: error: +[Subject entity] Failed to find a unique match for an NSEntityDescription to a managed object subclass
And then my app crashes with this Stack Trace
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'executeFetchRequest:error: A fetch request must have an entity.'
Workaround
I partially solved it by changing this FetchRequest
#FetchRequest(entity: Subject.entity(), sortDescriptors: [NSSortDescriptor(keyPath: \Subject.name, ascending: true)]) private var subjects: FetchedResults<Subject>
to this one
#FetchRequest(fetchRequest: NSFetchRequest(entityName: "Subject")) private var subjects: FetchedResults<Subject>
But still don't know what I did wrong in the first place and why is this stupid change solving my problem and I would like to know if there is another way to solve it.
When I use my app, sometimes, I have an error that appear, it seems to be randomly (or I didn't figure out when exactly...), then all my lists are empty (like if nothing were in CoreData).
But If I close my app and re-open it, lists appear without any problem...
I searched on stack overflow about this problem, but nothing is clear for me...
Error :
CoreData: warning: 'CDDetail' (0x2815e8790) from NSManagedObjectModel (0x2841bb8e0) claims 'CDDetail'.
2020-11-13 19:16:48.329773+0100 OrientationEPS[33705:3479327] [error] error: +[CDDetail entity] Failed to find a unique match for an NSEntityDescription to a managed object subclass
CoreData: error: +[CDDetail entity] Failed to find a unique match for an NSEntityDescription to a managed object subclass
Loading the persistent Container :
class OriEPS {
lazy var persistentContainer: NSPersistentContainer = {
let container = NSPersistentContainer(name: "OrientationEPS")
container.loadPersistentStores { description, error in
if let error = error {
fatalError("Unable to load persistent stores: \(error)")
}
}
return container
}()
var context: NSManagedObjectContext {
return persistentContainer.viewContext
}
And Here is my function to fetch the result :
private func fetchCDDetail(withId detailId:UUID) -> CDDetail? {
let fetchRequest = NSFetchRequest<CDDetail>(entityName: "CDDetail")
fetchRequest.predicate = NSPredicate(format: "id == %#", detailId as CVarArg)
fetchRequest.fetchLimit = 1
let fetchResult:[CDDetail]? = try? context.fetch(fetchRequest)
return fetchResult?.first
}
My CD Model
2 questions :
How should I solve this error ?
What does mean 0x2815e8790 ?
Edit 1 :
I can't find any other class call CDDetail
If I set Module to Current Product Module (nothing change)
Nothing change If I replace :
fetchRequest:NSFetchRequest = CDDetail.fetchRequest()
by
fetchRequest = NSFetchRequest(entityName:"CDDetail")
If I set codeGen to Category/Extension, it does not build and give me lots of errors :
You loaded model several times - that's the reason of those errors. Possible solution is to make container static.
Tested with Xcode 12.1 / iOS 14.1 - no errors:
class OriEPS {
private static var persistentContainer: NSPersistentContainer = {
let container = NSPersistentContainer(name: "CDOriEPS")
container.loadPersistentStores { description, error in
if let error = error {
fatalError("Unable to load persistent stores: \(error)")
}
}
return container
}()
var context: NSManagedObjectContext {
return Self.persistentContainer.viewContext
}
// ... other code
Note: other possible approach is to make OriEPS shared and use same instance everywhere you create it, but I did not investigate your solution deeply, so it is for your consideration.
I am trying to save a user generated image to core data. If I program the image the code works fine. But when the user selects the image I am getting the error Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value at jx = drawPlace.image!. I just want to fix that and the code will work. It is not having any problems saving into core data just the wrapping.
var jx = UIImage()
var drawPlace = UIImageView()
func save() {
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
let managedContext = appDelegate.persistentContainer.viewContext
let entity = NSEntityDescription.entity(forEntityName: "Item", in: managedContext)!
let item = NSManagedObject(entity: entity, insertInto: managedContext)
jx = drawPlace.image!
if let data = jx.pngData() {
item.setValue(data, forKey: "image")
}
Playing with core data and got stuck with this in Swift 2.0
var error: NSError?
let fetchedResults =
managedContext.executeFetchRequest(fetchRequest,
error: &error) as? [NSManagedObject]
Xcode error says "Extra argument in call" and when I remove error:&error it says "error not handled", so what's the new syntax?
In Swift 2.0 you have to use exception handling:
var fetchedResults : [NSManagedObject]?
do {
fetchedResults = try managedContext.executeFetchRequest(fetchRequest) as? [NSManagedObject]
} catch let error as NSError {
print("Error \(error.localizedDescription)")
}
Apple documentation
I've been chasing a bug for a while now and I can't figure it out. I have a class that takes a bunch of parsed data and then calls a method to create new core data "Article" object for each element created from the parsed data. I've shown how I declare the NSManagedObjectContext below.
You will also see the method
Article.createFLOArticleWithStructure(element, inManagedObjectContext: self.articleContext)
I placed this method in an extension to clean up the code. The method is show below.
import Foundation
class FLODataHandler : NSObject, FLOConnectionHandlerDelegate, FLOParserHandlerDelegate, TriathleteParserHandlerDelegate, VeloNewsParserHandlerDelegate, CyclingNewsParserHandlerDelegate, RoadBikeActionParserHandlerDelegate, IronmanParserHandlerDelegate
{
let appDelegate: AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
lazy var articleContext: NSManagedObjectContext = self.appDelegate.managedObjectContext!
func floParserHandlerDidFinishParsing(parserHandler : FLOParserHandler)
{
for element in self.floParserHandler!.XMLParsedDataArray!
{
// The pubDate, tilte and link and indicator have been added to the titleLinkArray. I will now add the data to a Core Data Entity
// in the Article+NewsFeedArticle class.
Article.createFLOArticleWithStructure(element, inManagedObjectContext: self.articleContext)
}
}
Extension Code
extension Article
{
class func createFLOArticleWithStructure(articleStructure: DateTitleLink, inManagedObjectContext context: NSManagedObjectContext) -> (Article)
{
// Core data is much simpler in Swift. I have not commented this code since I do not know if it's working yet.
var article = Article()
//var entity = NSEntityDescription("Article", inManagedObjectContext: context)
let fetchRequest = NSFetchRequest(entityName: "Article")
let predicate = NSPredicate(format: "feed == 'FLO Cycling' AND title == %#", articleStructure.title!)
let sortDescriptor = NSSortDescriptor(key: "pubDate", ascending: true)
fetchRequest.sortDescriptors = [sortDescriptor]
// Set up NSError
var fetchError : NSError?
// When you perform a fetch the returned object is an array of the Atricle Entities.
let fetchedObjects = context.executeFetchRequest(fetchRequest, error: &fetchError) as! [Article]
if fetchedObjects.count > 1
{
println("Error! in Article+NewFeedArticle.swift")
}
else if fetchedObjects.count == 0
{
article = NSEntityDescription.insertNewObjectForEntityForName("Article", inManagedObjectContext: context) as! Article
article.feed = "FLO Cycling"
article.pubDate = articleStructure.date!
article.title = articleStructure.title!
article.link = articleStructure.link!
article.theNewArticle = NSNumber(int: 1)
var error : NSError?
if(context.save(&error))
{
println(error!.localizedDescription)
}
}
else if fetchedObjects.count == 1
{
article = fetchedObjects[fetchedObjects.endIndex - 1]
}
return article
}
When I run the code I get stopped on the following line of the extension code and receive the following errors.
article = NSEntityDescription.insertNewObjectForEntityForName("Article", inManagedObjectContext: context) as! Article
CoreData: error: Failed to call designated initializer on
NSManagedObject class 'FLOCycling1_1_1.Article' CoreData: warning:
Unable to load class named 'Article' for entity 'Article'. Class not
found, using default NSManagedObject instead. Could not cast value of
type 'NSManagedObject_Article_' (0x7fe59c3515e0) to
'FLOCycling1_1_1.Article' (0x106139f70).
I've read online about using a prefix in the data model. I've added this to no avail. If you have any idea how I can fix this error I would appreciate the help.
ADDED****
Here is the Article.swift file on request.
import Foundation
import CoreData
#objc class Article: NSManagedObject
{
#NSManaged var feed: String
#NSManaged var link: String
#NSManaged var pubDate: NSDate
#NSManaged var theNewArticle: NSNumber
#NSManaged var title: String
}
Take care,
Jon
The issue had to do with my declaration of Article in this line here.
var article = Article()
In the Swift version calling the line of code above allocates and initializes memory for the Article. In the Objective-C version of my code I called the following.
Article *article = nil;
While I am not sure why, allocating and initializing the Article is the issue. I found this post here about a similar error.
Failed to call designated initializer on NSManagedObject class 'ClassName'
To fix this I changed the code to
var article = Article?()
To be clear, I also changed the Article class to ProjectName.Article.
I hope this helps someone else.
Take care,
Jon