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