致命错误:在展开可选值错误Swift时意外发现nil

时间:2015-11-04 23:47:13

标签: ios swift

我收到了我在标题中写的错误,在查看了所有其他堆栈溢出线程后,但没有一个真正解释问题的来源。

当我启动应用程序时,它会立即崩溃并以红色突出显示该行:

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

应用启动的主视图控制器具有以下代码:

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 个答案:

答案 0 :(得分:3)

执行let modelURL = NSBundle.mainBundle().URLForResource("HitList", withExtension: "mom")!时,找不到文件HitList,结果为nil。你无法解开零。

答案 1 :(得分:0)

根据Apple的URLForResource方法:

  

返回由指定名称和扩展名标识并驻留在给定bundle目录中的资源文件的文件URL。

并返回:

  

资源文件的文件URL,如果找不到该文件,则为nil。如果nil参数指定的包不存在或不是可读目录,则此方法也返回bundlePath

你需要在打开它之前进行检查,记住每次使用!运算符解包一个可选项,你对编译器说变量总是有一个值,你可以使用可选的绑定来修复它。以下方式:

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

或者在Swift 2.0中使用新的guard语句,如下所示;

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

我希望这对你有所帮助。

答案 2 :(得分:0)

您正试图打开一条在线上不存在的值。

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

找到您尝试获取的文件并确保其存在,并将其命名为HitList.momd。而这样做......

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

因此,万一文件不存在,您的应用程序不会崩溃。

答案 3 :(得分:0)

谢谢,这有效。 John Doe没有工作,因为它仍然提供了错误消息,但在这种情况下将URLForResource更改为xcdatamodeld名称的名称。