你能在打开包装时发现 nil 吗?
Posted
技术标签:
【中文标题】你能在打开包装时发现 nil 吗?【英文标题】:can you spot the nil while unwrapping? 【发布时间】:2017-05-03 00:41:41 【问题描述】:我试图在展开时找到 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
【问题讨论】:
请发布相关代码。 请学习***.com/questions/32170456/… "我试图在展开时找到 nil 在哪里" 不,你没有尝试。您的代码 (!
) 中的每个感叹号都表示“请让我崩溃”。如果这正是发生的事情,你不能抱怨。要找到nil
,您所要做的就是自己寻找它。不要使用任何感叹号! 安全地执行所有向下转换和解包 Optionals 并在调试器中单步执行以查看实际发生的情况。
@rmaddy 我认为他们会帮助您了解我在做什么,我也对您提出的问题提出了质疑,我被卡住了。感谢您抽出宝贵时间发表评论。
@matt 我试图安全地解开 if 中的 valuew,但编译器抱怨我没有初始化所有值。感谢您抽出宝贵时间发表评论。
【参考方案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
当你绝对确定值不可能为零时,你真的应该只“使用强制”。
【讨论】:
以上是关于你能在打开包装时发现 nil 吗?的主要内容,如果未能解决你的问题,请参考以下文章
在 SwiftUI 类中调用包装的 UIViewController 函数时获得 nil
Swift UIViewController tableView.reloadData nil 在第二次调用时包装