iosswiftcore-datansentitydescription

NSEntityDescription returning nil while unwrapping an optional value


that's what is happening: I'm new to swift and I don't quite understand CoreData yet, but I'm following some tutorials on youtube so I can learn it. Now, when I run my app, it crashes and then get an error "fatal error: unexpectedly found nil while unwrapping an Optional value"

detail: this code is from one tutorial for helping new people to swift using CoreData.

Here is the code:

import UIKit import CoreData

class SwiftCoreDataHelper: NSObject {

class func directoryForDatabaseFilename()->NSString{
    return NSHomeDirectory().stringByAppendingString("/Library/Private Documents")
}


class func databaseFilename()->NSString{
    return "database.sqlite";
}


class func managedObjectContext()->NSManagedObjectContext{

    var error:NSError? = nil

    NSFileManager.defaultManager().createDirectoryAtPath(SwiftCoreDataHelper.directoryForDatabaseFilename() as String, withIntermediateDirectories: true, attributes: nil, error: &error)

    let path:NSString = "\(SwiftCoreDataHelper.directoryForDatabaseFilename()) + \(SwiftCoreDataHelper.databaseFilename())"

    let url:NSURL = NSURL(fileURLWithPath: path as String)!

    let managedModel:NSManagedObjectModel = NSManagedObjectModel.mergedModelFromBundles(nil)!

    var storeCoordinator:NSPersistentStoreCoordinator = NSPersistentStoreCoordinator(managedObjectModel: managedModel)

    if !(storeCoordinator.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: nil, error:&error ) != nil){
        if (error != nil){
            println(error!.localizedDescription)
            abort()
        }
    }

    var managedObjectContext = NSManagedObjectContext(concurrencyType: NSManagedObjectContextConcurrencyType.MainQueueConcurrencyType)

    managedObjectContext.persistentStoreCoordinator = storeCoordinator

    return managedObjectContext


}

class func insertManagedObject(className:NSString, managedObjectConect:NSManagedObjectContext)->AnyObject{

    let managedObject:NSManagedObject = NSEntityDescription.insertNewObjectForEntityForName(className as String, inManagedObjectContext: managedObjectConect) as! NSManagedObject

    return managedObject

}

class func saveManagedObjectContext(managedObjectContext:NSManagedObjectContext)->Bool{
    if managedObjectContext.save(nil){
        return true
    }else{
        return false
    }
}


class func fetchEntities(className:NSString, withPredicate predicate:NSPredicate?, managedObjectContext:NSManagedObjectContext)->NSArray{
    let fetchRequest:NSFetchRequest = NSFetchRequest()
    let entetyDescription:NSEntityDescription = NSEntityDescription.entityForName(className as String, inManagedObjectContext: managedObjectContext)!

    fetchRequest.entity = entetyDescription
    if (predicate != nil){
        fetchRequest.predicate = predicate!
    }

    fetchRequest.returnsObjectsAsFaults = false
    let items:NSArray = managedObjectContext .executeFetchRequest(fetchRequest, error: nil)!

    return items
}

}

Then, it crashes right here:

    **let entetyDescription:NSEntityDescription = NSEntityDescription.entityForName(className as String, inManagedObjectContext: managedObjectContext)!** // Crashes right here, "Thead 1: EXC_BAD_INSTRUCTION(code=EXC_I386_INVOP,subcode=0x0)

What should I do to fix this error? I'm in this thread for like 3 days and I don't know where to run!

Thanks in advance.

UPDATE

Here's my code:

import UIKit import CoreData

class MainViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {

@IBOutlet weak var mainImage: UIImageView!
@IBOutlet weak var tableView: UITableView!
var namesListArray:NSMutableArray = NSMutableArray()



override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
}

override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated)
    loadData()
}

func loadData() {
    namesListArray.removeAllObjects()
    let moc:NSManagedObjectContext = SwiftCoreDataHelper.managedObjectContext()
    let results:NSArray = SwiftCoreDataHelper.fetchEntities(NSStringFromClass(Recipe), withPredicate: nil, managedObjectContext: moc)
    for recipe in results {
        let singleRecipe:Recipe = recipe as! Recipe
        let recipeDict:NSDictionary = ["identifier":singleRecipe.identifier, "recipelabel":singleRecipe.recipelabel, "recipeimage":singleRecipe.recipeimage]
        namesListArray.addObject(recipeDict)
    }
    tableView.reloadData()     }

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return namesListArray.count
}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

    let cell:CustomCellTableViewCell = tableView.dequeueReusableCellWithIdentifier("customCell", forIndexPath: indexPath) as! CustomCellTableViewCell
    let recipeDict:NSDictionary = namesListArray.objectAtIndex(indexPath.row) as! NSDictionary
    let recipeName = recipeDict.objectForKey("recipelabel") as! String
    let imageData:NSData = recipeDict.objectForKey("recipeimage") as! NSData
    let recipeImage: UIImage = UIImage(data: imageData)!
    cell.customLabel.text = recipeName
    var recipeImageFrame:CGRect = cell.customImage.frame
    recipeImageFrame.size = CGSizeMake(75,75)
    cell.customImage.frame = recipeImageFrame
    cell.customImage.image = recipeImage

    return cell
}

}

predicate NSPredicate? nil None

Maybe the error is around here? If so, I can't see it. Any idea?

And thanks again!!!


Solution

  • The className being passed in most likely has a typo in it so you are not able to retrieve the entity from the model. Compare what is being passed in to what the model is expecting and you will find the error.

    Update

    Print out the className in that method. What is getting printed out? Does it match what is in the model? Class name is rarely the same as the entity name.