2016-11-07 53 views
-7

经过更多的研究和审查文章指出:我总结我的代码实际上是正确的。我从模拟器文档文件夹中删除了我的应用程序的.plist文件,从而允许从我的新视图控制器创建新文件。SWIFT的非常新的致命错误意外地发现零,同时展开一个可选的价值

我收到一个致命错误。我的应用的构建没有错误,模拟器;然而,没有显示,应用程序崩溃。调试器窗口指出“fata错误:在解包可选值时意外发现nil”。我相信这个错误是因为forKey指的是引用一个空数组的列表/

import UIKit 

class AllListsViewController: UITableViewController, ListDetailViewControllerDelegate { 

    override func viewDidLoad() { 
     super.viewDidLoad() 

    } 

    override func didReceiveMemoryWarning() { 
     super.didReceiveMemoryWarning() 
     // Dispose of any resources that can be recreated. 
    } 



    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 

     return lists.count 
    } 

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 
     let cell = makeCell(for: tableView) 

     let checklist = lists[indexPath.row] 
     cell.textLabel!.text = checklist.name 
     cell.accessoryType = .detailDisclosureButton 

     return cell 
    } 

    func makeCell(for tableView: UITableView) -> UITableViewCell { 
     let cellIdentifier = "Cell" 
     if let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier) { 
      return cell 
     } else { 
      return UITableViewCell(style: .default, reuseIdentifier: cellIdentifier) 
     } 
    } 

    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 
     let checklist = lists[indexPath.row] 
     performSegue(withIdentifier: "ShowChecklist", sender: checklist) 

} 

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 
     if segue.identifier == "ShowChecklist" { 
      let controller = segue.destination as! ChecklistViewController 
      controller.checklist = sender as! Checklist 
     } else if segue.identifier == "AddChecklist" { 
      let navigationController = segue.destination 
               as! UINavigationController 
      let controller = navigationController.topViewController 
               as! ListDetailViewController 
      controller.delegate = self 
      controller.checklistToEdit = nil 
     } 
    } 



    var lists: [Checklist] 


    required init?(coder aDecoder: NSCoder) { 

     lists = [Checklist]() 
     super.init(coder: aDecoder) 
     loadChecklists() 
     } 


    override func tableView(_ tableView: UITableView, 
          commit editingStyle: UITableViewCellEditingStyle, 
          forRowAt indexPath: IndexPath) { 
     lists.remove(at: indexPath.row) 
     let indexPaths = [indexPath] 
     tableView.deleteRows(at: indexPaths, with: .automatic) 
    } 

    func listDetailViewControllerDidCancel(
     _ controller: ListDetailViewController) { 
     dismiss(animated: true, completion: nil) 
    } 
    func listDetailViewController(_ controller: ListDetailViewController, 
            didFinishAdding checklist: Checklist) { 
     let newRowIndex = lists.count 
     lists.append(checklist) 
     let indexPath = IndexPath(row: newRowIndex, section: 0) 
     let indexPaths = [indexPath] 
     tableView.insertRows(at: indexPaths, with: .automatic) 
     dismiss(animated: true, completion: nil) 
    } 
    func listDetailViewController(_ controller: ListDetailViewController, 
            didFinishEditing checklist: Checklist) { 
     if let index = lists.index(of: checklist) { 
      let indexPath = IndexPath(row: index, section: 0) 
      if let cell = tableView.cellForRow(at: indexPath) { 
       cell.textLabel!.text = checklist.name 
      } 
     } 
     dismiss(animated: true, completion: nil) 
    } 

    override func tableView(_ tableView: UITableView, 
          accessoryButtonTappedForRowWith indexPath: IndexPath) { 

     let navigationController = storyboard!.instantiateViewController(
      withIdentifier: "ListDetailNavigationController") 
      as! UINavigationController 

     let controller = navigationController.topViewController 
       as! ListDetailViewController 
     controller.delegate = self 

     let checklist = lists[indexPath.row] 
     controller.checklistToEdit = checklist 

     present(navigationController, animated: true, completion: nil) 
    } 

    func documentsDirectory() -> URL { 
     let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask) 
     return paths[0] 
    } 

    func dataFilePath() -> URL { 
     return documentsDirectory().appendingPathComponent("Checklists.plist") 
    } 

    func saveChecklists() { 
     let data = NSMutableData() 
     let archiver = NSKeyedArchiver(forWritingWith: data) 

     archiver.encode(lists, forKey: "Checklists") 

     archiver.finishEncoding() 
     data.write(to: dataFilePath(), atomically: true) 
    } 

    func loadChecklists() { 
     let path = dataFilePath() 
     if let data = try? Data(contentsOf: path) { 
      let unarchiver = NSKeyedUnarchiver(forReadingWith: data) 

      *lists = unarchiver.decodeObject(forKey: "Checklists") as! [Checklist]* ****The Error occurs on this line**** 

      unarchiver.finishDecoding() 
     } 
    } 
} 
+1

调试你的代码,找出哪一行确切的程序崩溃。检查你的初始化器是否真的被调用。我从来没有见过像你那样定制控制器初始化器。我怀疑你的'list'从不初始化。空数组在你的情况下不会引发错误,空数组不等于'nil'。 –

回答

0

as!明确展开可选项。如?如果向下转换失败,将通过简单地返回零来防止应用程序崩溃。

if let checklist = (NSKeyedUnarchiver(forReadingWith: data)?.decodeObject(forKey: "Checklists")) as? [Checklist] { 
    lists = checklist 
} 
else { 
    // set lists as appropriate 
} 
+1

加上这个,你可能想把'lists'设置成else块中空的'Checklist'数组 – Danoram

相关问题