2016-11-07 21 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

相關問題