Nicholas Piccoli Nicholas Piccoli - 4 months ago 80
Swift Question

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!!!

Answer

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.

Comments