我试图在打开时找到nil在哪里。这是我的代码片段。发现致命错误的行位于:
第一档:
date = dateFormatter().date(from: dictionary[kDATE] as! String)!
第二档:
self.allLists.append(ShoppingList.init(dictionary: currentList))
这是来自shoppingList.swift文件,该函数在控制器中调用
import Foundation
import Firebase
class ShoppingList{
let name: String
var totalPrice: Float
var totalItems: Int
var id: String
var date: Date
var ownerId: String
init(_name: String, _totalPrice: Float = 0, _id: String = "") {
name = _name
totalPrice = _totalPrice
totalItems = 0
id = _id
date = Date()
ownerId = "1234"
}
//creates shopping list item from this dictionary
init(dictionary: NSDictionary) {
name = dictionary[kNAME] as! String
totalPrice = dictionary[kTOTALPRICE] as! Float
totalItems = dictionary[kTOTALITEMS] as! Int
id = dictionary[kSHOPPINGLISTID] as! String
date = dateFormatter().date(from: dictionary[kDATE] as! String)!
ownerId = dictionary[kOWNERID] as! String
}
func dictionaryFromItem(item: ShoppingList) -> NSDictionary {
return NSDictionary(objects: [item.name, item.totalPrice, item.totalItems, item.id, dateFormatter().string(from: item.date), item.ownerId], forKeys: [kNAME as NSCopying, kTOTALPRICE as NSCopying, kTOTALITEMS as NSCopying, kSHOPPINGLISTID as NSCopying, kDATE as NSCopying, kOWNERID as NSCopying])
}
这是控制器:
import UIKit
import KRProgressHUD
class AllListsViewController: UIViewController, UITableViewDataSource,UITableViewDelegate{
@IBOutlet weak var tableView: UITableView!
var allLists:[ShoppingList] = []
var nameTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
loadLists()
}
//MARK: TableView DataSource
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return allLists.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
let shoppingList = allLists[indexPath.row]
cell.textLabel?.text = shoppingList.name
return cell
}
//MARK: IBActions
@IBAction func addBarButonItemPressed(_ sender: Any) {
let alertController = UIAlertController(title: "Create Shopping List", message: "Enter the shopping list name", preferredStyle: .alert)
alertController.addTextField{ (nameTextField) in
nameTextField.placeholder = "Name"
self.nameTextField = nameTextField
}
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel){ (action) in
}
let saveAction = UIAlertAction(title: "Save", style: .default){ (action) in
if self.nameTextField.text != ""{
self.createShoppingList()
}else{
KRProgressHUD.showWarning(message: "Name is empty!")
}
}
alertController.addAction(cancelAction)
alertController.addAction(saveAction)
self.present(alertController,animated: true, completion:nil)
}
//MARK: LoadList
func loadLists(){
//.values has all the info of the child
firebase.child(kSHOPPINGLIST).child("1234").observe(.value, with: {
snapshot in
self.allLists.removeAll()
//if we actually received smthing from firebase
if snapshot.exists(){
let sorted = ((snapshot.value as! NSDictionary).allValues as NSArray).sortedArray(using: [NSSortDescriptor(key: kDATE,ascending: false)])
for list in sorted {
let currentList = list as! NSDictionary
self.allLists.append(ShoppingList.init(dictionary: currentList))
}
} else {
print("no snapshot")
}
self.tableView.reloadData()
})
}
//MARK: Helper functions
func createShoppingList(){
let shoppingList = ShoppingList(_name: nameTextField.text!)
shoppingList.saveItemInBackground(shoppingList: shoppingList){ (error) in
if error != nil{
KRProgressHUD.showError(message: "Error creating shopping list")
return
}
}
}
}
数据格式化程序也是另一个文件中的一个小函数。
import Foundation
import UIKit
private let dateFormat = "yyyyMMDDHHmmss"
func dateFormatter() -> DateFormatter {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = dateFormat
return dateFormatter
}
答案 0 :(得分:1)
所以你在这一行上有一个强制向下倾斜和强制可选的解包:
date = dateFormatter().date(from: dictionary[kDATE] as! String)!
您的字典未返回字符串,或者字典中的字符串无法作为日期处理。我猜这是第一个问题,因为日期通常存储为epoch。
尝试使用此代替上面的行。在顶部添加断点并逐步执行:
print(dictionary[kDATE])
if let dictValue = dictionary[kDATE] as? String {
print(dictValue)
if let unwrappedDate = dateFormatter().date(from: dictValue) {
date = unwrappedDate
}
}
如果在第一个if-let上失败,则返回值不是字符串。如果第二个失败则问题在于日期格式化程序无法读取格式。
第一个打印可能会告诉您要投射到什么类型的线索,第二个可以帮助您修复格式。
强行展开时要小心,
optionalVar!
或用于向下转发。
unknownType as! Type
当你绝对确定价值不会为零时,你应该只使用“力”。