1
votes

I am getting the error that i wrote in the title and after looking at all the other stack overflow threads but none of them really explain where the problem comes from.

When I launch the application it instantly crashes and highlights this line in red:

let modelURL = NSBundle.mainBundle().URLForResource("HitList", withExtension: "momd")!

My main View controller that the app launches to has this code:

import UIKit
import CoreData

class ViewController: UIViewController, UITableViewDataSource {


@IBOutlet weak var tableView: UITableView!
var subjects = [NSManagedObject]()
override func viewDidLoad() {
    super.viewDidLoad()

    tableView.registerClass(UITableViewCell.self,
        forCellReuseIdentifier: "Cell")
}

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

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

        let cell =
        tableView.dequeueReusableCellWithIdentifier("Cell")

        let check = subjects[indexPath.row]

        cell!.textLabel!.text =
            check.valueForKey("name") as? String

        return cell!
}
override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()

}

@IBAction func addName(sender: AnyObject) {
    let alert = UIAlertController(title: "New Subject", message: "Add a new Subject", preferredStyle: .Alert)
    let saveAction = UIAlertAction(title: "Save",
        style: .Default,
        handler: { (action:UIAlertAction) -> Void in

            let textField = alert.textFields!.first
            self.saveName(textField!.text!)
            self.tableView.reloadData()
    })


    let cancelAction = UIAlertAction(title: "Cancel",
        style: .Default) { (action: UIAlertAction) -> Void in
    }

    alert.addTextFieldWithConfigurationHandler {
        (textField: UITextField) -> Void in
    }
    alert.addAction(saveAction)
    alert.addAction(cancelAction)

    presentViewController(alert,
        animated: true,
        completion: nil)
}
func saveName(name: String) {

    let appDelegate =
    UIApplication.sharedApplication().delegate as! AppDelegate

    let managedContext = appDelegate.managedObjectContext


    let entity =  NSEntityDescription.entityForName("Subjects",
        inManagedObjectContext:managedContext)

    let check = NSManagedObject(entity: entity!,
        insertIntoManagedObjectContext: managedContext)


    check.setValue(name, forKey: "name")


    do {
        try managedContext.save()

        subjects.append(check)
    } catch let error as NSError  {
        print("Could not save \(error), \(error.userInfo)")
    }
}
override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)


    let appDelegate =
    UIApplication.sharedApplication().delegate as! AppDelegate

    let managedContext = appDelegate.managedObjectContext


    let fetchRequest = NSFetchRequest(entityName: "Subjects")


    do {
        let results =
        try managedContext.executeFetchRequest(fetchRequest)
        subjects = results as! [NSManagedObject]
    } catch let error as NSError {
        print("Could not fetch \(error), \(error.userInfo)")
    }
    func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle,forRowAtIndexPath indexPath: NSIndexPath) {

    }
}

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if (segue.identifier == "ShowAssesment") {
        let indexPath = tableView.indexPathForCell((sender as? UITableViewCell)!)
        let listVC = segue.destinationViewController as? AssesmentViewController

        let subject = subjects[indexPath!.row]

        listVC?.assesments = ["Death"]
    }

}

}
4
Thank You, that has worked and i was able to change it, one other problem that i have had is that when i click on a segue it doesn't transfer to the other table view even though i have made a show segue with the id ShowAssesmentJames Lamberth

4 Answers

0
votes

You're trying to unwrap a value that doesn't exist on the line..

let modelURL = NSBundle.mainBundle().URLForResource("HitList", withExtension: "momd")!

Locate the file you're trying to obtain and make sure it exists and that it's called HitList.momd. And do this instead...

var modelURL = NSBundle.mainBundle().URLForResource("HitList", withExtension: "momd")

So just in case the file doesn't exist your app doesn't crash.

3
votes

When let modelURL = NSBundle.mainBundle().URLForResource("HitList", withExtension: "mom")! is executed, the file HitList is not found and the result is nil. You cannot unwrap nil.

0
votes

The URLForResource method according to Apple:

Returns the file URL for the resource file identified by the specified name and extension and residing in a given bundle directory.

And returns :

The file URL for the resource file or nil if the file could not be located. This method also returns nil if the bundle specified by the bundlePath parameter does not exist or is not a readable directory.

You need to check before unwraps it, remember every time you use the ! operator to unwrap an optional you say to the compiler that the variable always have a value, you can fix it using optional binding like in the following way:

if let modelURL = NSBundle.mainBundle().URLForResource("HitList", withExtension: "momd") {
    // do whatever you what with the value 
}
else {
   // the value is nil
}

Or instead use the new guard statement in Swift 2.0 like in the following way;

guard let let modelURL = NSBundle.mainBundle().URLForResource("HitList", withExtension: "momd") else {
   // the value is nil
   return
}

I hope this help you.

0
votes

Thank you, that has worked. John Doe's didn't work as it still gave the error message but changing the URLForResource in this case to the name of the xcdatamodeld name.