我已经用Google搜索并阅读了很多有关此主题的问题和答案,但我仍然无法解决我的问题。我有一个连接到firebase的项目,其中一个tableView连接到该信息。弹出以下错误:
在解包可选值时意外地发现了nil。
我已经检查了UIButton
s,UILabel
等之间的所有连接,并且最重要的是我尝试使用断点来查找错误。但是我似乎无法理解解决方案。来自项目的代码和消息以及错误:
@IBOutlet weak var addButton: UIBarButtonItem!
let listToUsers = "ListToUsers"
var backgroundNr = 0
var items: [GroceryItem] = []
let ref = FIRDatabase.database().reference(withPath: "grocery-items")
let usersRef = FIRDatabase.database().reference(withPath: "online")
var user: User!
var userCountBarButtonItem: UIBarButtonItem!
var counter = 1
override func viewDidLoad() {
super.viewDidLoad()
if user?.email == "tor@gmail.com" {
addButton.isEnabled = false
}
tableView.allowsMultipleSelectionDuringEditing = false
userCountBarButtonItem = UIBarButtonItem(title: "1",
style: .plain,
target: self,
action: #selector(userCountButtonDidTouch))
userCountBarButtonItem.tintColor = UIColor.white
navigationItem.leftBarButtonItem = userCountBarButtonItem
usersRef.observe(.value, with: { snapshot in
if snapshot.exists() {
self.userCountBarButtonItem?.title = snapshot.childrenCount.description
} else {
self.userCountBarButtonItem?.title = "0"
}
})
ref.queryOrdered(byChild: "completed").observe(.value, with: { snapshot in
var newItems: [GroceryItem] = []
for item in snapshot.children {
let groceryItem = GroceryItem(snapshot: item as! FIRDataSnapshot)
newItems.append(groceryItem)
}
self.items = newItems
self.tableView.reloadData()
})
FIRAuth.auth()!.addStateDidChangeListener { auth, user in
guard let user = user else { return }
self.user = User(authData: user)
let currentUserRef = self.usersRef.child(self.user!.uid)
currentUserRef.setValue(self.user!.email)
currentUserRef.onDisconnectRemoveValue()
}
}
// MARK: UITableView Delegate methods
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ItemCell", for: indexPath) as! SubjectTableViewCell
let groceryItem = items[indexPath.row]
if backgroundNr == 0 {
cell.backgroundColor = UIColor(red: 222/255, green: 164/255, blue: 50/255, alpha: 0.6)
backgroundNr += 1
} else {
cell.backgroundColor = UIColor.white
backgroundNr -= 1
}
cell.textLabel?.text = groceryItem.name
cell.detailTextLabel?.text = groceryItem.addedByUser
toggleCellCheckbox(cell, isCompleted: groceryItem.completed)
return cell
}
override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
let groceryItem = items[indexPath.row]
groceryItem.ref?.removeValue()
}
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
guard let cell = tableView.cellForRow(at: indexPath) else { return }
let groceryItem = items[indexPath.row]
let toggledCompletion = !groceryItem.completed
toggleCellCheckbox(cell, isCompleted: toggledCompletion)
groceryItem.ref?.updateChildValues([
"completed": toggledCompletion
])
}
func toggleCellCheckbox(_ cell: UITableViewCell, isCompleted: Bool) {
if !isCompleted {
cell.accessoryType = .none
cell.textLabel?.textColor = UIColor.black
cell.detailTextLabel?.textColor = UIColor.black
} else {
cell.accessoryType = .checkmark
cell.textLabel?.textColor = UIColor.gray
cell.detailTextLabel?.textColor = UIColor.gray
}
}
// MARK: Add Item
@IBAction func addButtonTapped(_ sender: Any) {
let alert = UIAlertController(title: "Kunskaps Område",
message: "Lägg till objekt",
preferredStyle: .alert)
let saveAction = UIAlertAction(title: "Spara",
style: .default) { _ in
// 1
guard let textField = alert.textFields?.first,
let text = textField.text else { return }
// 2
let groceryItem = GroceryItem(name: text,
addedByUser: self.user!.email,
completed: false)
// 3
let groceryItemRef = self.ref.child(text.lowercased())
// 4
groceryItemRef.setValue(groceryItem.toAnyObject())
}
let cancelAction = UIAlertAction(title: "Cancel",
style: .default)
alert.addTextField()
alert.addAction(saveAction)
alert.addAction(cancelAction)
present(alert, animated: true, completion: nil)
}
func userCountButtonDidTouch() {
performSegue(withIdentifier: listToUsers, sender: nil)
}
@IBAction func startClockTapp(_ sender: Any) {
Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(GroceryListTableViewController.updateCounter), userInfo: nil, repeats: true)
}
func updateCounter() {
counter += 1
let clock = String(counter)
print(clock)
let clockCurrent = Clock(name: clock, addedByUser: self.user!.email)
let clockCurrentRef = self.ref.child(clock.lowercased())
clockCurrentRef.setValue(clockCurrent.toAnyObject())
}
当使用断点来定位错误发生的位置时,它似乎位于以下函数中:(“UITable view delegate methods”中的第一行代码
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items.count
}
如果我使用断点错误,我现在不会,但如果它有帮助,那就是我得到的结果。
“杂货店”对象struct文件的代码如下:
import Foundation
import Firebase
struct GroceryItem {
let key: String
let name: String
let addedByUser: String
let ref: FIRDatabaseReference?
var completed: Bool
init(name: String, addedByUser: String, completed: Bool, key: String = "") {
self.key = key
self.name = name
self.addedByUser = addedByUser
self.completed = completed
self.ref = nil
}
init(snapshot: FIRDataSnapshot) {
key = snapshot.key
let snapshotValue = snapshot.value as! [String: AnyObject]
name = snapshotValue["name"] as! String
addedByUser = snapshotValue["addedByUser"] as! String
completed = snapshotValue["completed"] as! Bool
ref = snapshot.ref
}
func toAnyObject() -> Any {
return [
"name": name,
"addedByUser": addedByUser,
"completed": completed
]
}
}
Firebase上的数据库内容结构如下:
educationlevel-e230e
杂货项
基本错误消息的完整字符串:
致命错误:在展开Optional值时意外发现nil 2016-12-24 01:22:54.799117 EducationLevel [1077:263810]
致命错误: 在展开可选值时意外发现nil
我真的无法通过我自己或网络上的任何地方找到这个问题的答案,真的很感激,如果我能得到一些帮助(对不起英语可能不好,我来自瑞典;)) p>
(如果您需要更多来自错误消息或类似内容的字符串,我会立即更新此问题)
谢谢!来自瑞典的Tor。