致命错误:在从Firebasedatabase加载值时展开“可选”值时意外发现nil

时间:2016-09-09 14:47:46

标签: ios firebase swift2 firebase-realtime-database

我很快乐。我试图指责自己。我知道这是常见问题,但我希望能得到帮助。当我运行应用程序时。我得到了"致命错误:在解开一个可选值"时意外地发现了nil。

    import Foundation
    import Firebase
    import FirebaseDatabase
    import FirebaseStorage
    import FirebaseAuth

    struct TodoItemDatabase {
    var eventID: String!
    var title: String!
    var staff: String!
    var location: String!
    var starts: String!
    var ends: String!
    var rpeat: String!
    var imageName: String!
    var description: String!
    var secondPhoto: String!
    var ref: FIRDatabaseReference?
    var key: String!
    var isCompleted: Bool

init (eventID: String!, title: String,staff:String, location: String,starts: String, ends: String, rpeat: String, imageName: String, description: String, secondPhoto: String, key: String = "", isCompleted: Bool){
    self.eventID = eventID
    self.title = title
    self.staff = staff
    self.location = location
    self.starts = starts
    self.ends = ends
    self.rpeat = rpeat
    self.imageName = imageName
    self.description = description
    self.secondPhoto = secondPhoto
    self.key = key
    self.ref = FIRDatabase.database().reference()
    self.isCompleted = isCompleted
}
init(snapshot: FIRDataSnapshot){

    **//I get the error from here. However, I think the main reason in tableview below** 

    self.eventID = snapshot.value!["eventID"] as! String
    self.title = snapshot.value!["title"] as! String
    self.staff = snapshot.value!["staff"] as! String
    self.location = snapshot.value!["location"] as! String
    self.starts = snapshot.value!["starts"] as! String
    self.ends = snapshot.value!["ends"] as! String
    self.rpeat = snapshot.value!["rpeat"] as! String
    self.imageName = snapshot.value!["imageName"] as! String
    self.description = snapshot.value!["description"] as! String
    self.secondPhoto = snapshot.value!["secondPhoto"] as! String
    self.key = snapshot.key
    self.ref = snapshot.ref
    self.isCompleted = snapshot.value!["isCompleted"] as! Bool
}
func toAnyObject() -> [String: AnyObject] {
    return ["eventid": eventID, "title": title, "staff": staff, "location": location, "starts": starts, "ends": ends, "rpeat": rpeat, "imageName": imageName, "description": description, "secondPhoto": secondPhoto, "isCompleted": isCompleted]
}

}

但是,当我运行应用程序时,加载tableview。看来这个错误。

    import UIKit
    import Firebase
    import FirebaseAuth
    import FirebaseDatabase
    import FirebaseStorage

    var toDoList:[TodoItemDatabase] = [TodoItemDatabase]()

    class CurrentEventViewController: UIViewController, UITableViewDelegate {

var databaseRef: FIRDatabaseReference!{
    return FIRDatabase.database().reference()
}

var storageRef: FIRStorageReference!

@IBOutlet var toDoListTable: UITableView!

override func viewDidLoad() {
    super.viewDidLoad()



}

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


func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return toDoList.count

}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! myCell
    let todoItem = toDoList[indexPath.row]
    storageRef = FIRStorage.storage().referenceForURL(toDoList[indexPath.row].imageName)
    storageRef.dataWithMaxSize(1 * 1024 * 1024) { (data, error) in

        if error == nil {
            dispatch_async(dispatch_get_main_queue(), { 
                if let data = data {
                    cell.myImageView.image = UIImage(data: data)
                }

            })
        } else {
            print(error!.localizedDescription)
        }


    }
    cell.myLabel.text = todoItem.title!

    return cell


}


func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {

    if editingStyle == UITableViewCellEditingStyle.Delete {

        let ref = toDoList[indexPath.row]
        ref.ref?.removeValue()
        toDoList.removeAtIndex(indexPath.row)



        toDoListTable.reloadData()
    }

}


override func viewDidAppear(animated: Bool) {

    toDoListTable.reloadData()

}
override func viewWillAppear(animated: Bool) {
    let postRef = FIRDatabase.database().reference().child("posts").queryOrderedByChild("isCompleted").queryEqualToValue(false)
    postRef.observeEventType(.Value, withBlock: { (snapshot) in
        var newPosts = [TodoItemDatabase]()
        for post in snapshot.children{
            **// I think the reason is the line after.** 
            let post = TodoItemDatabase(snapshot: post as! FIRDataSnapshot)
            newPosts.insert(post, atIndex: 0)
        }
        toDoList = newPosts
        dispatch_async(dispatch_get_main_queue(), { 
            self.toDoListTable.reloadData()
        })
    }) { (error) in
        print(error.localizedDescription)
    }
}


func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {

    storageRef = FIRStorage.storage().referenceForURL(toDoList[indexPath.row].imageName)
    let storageRef1 = FIRStorage.storage().referenceForURL(toDoList[indexPath.row].secondPhoto)
    let itemSelected = toDoList[indexPath.row]
    storageRef.dataWithMaxSize(1 * 1024 * 1024) { (data, error) in
        if error == nil
        {
            dispatch_async(dispatch_get_main_queue(), {
                if let data = data
                {
                    storageRef1.dataWithMaxSize(1 * 1024 * 1024) { (data1, error) in

                        if error == nil
                        {
                            dispatch_async(dispatch_get_main_queue(), {
                                if let data1 = data1
                                {
                                    let detailVC:DetailViewController = self.storyboard?.instantiateViewControllerWithIdentifier("DetailViewController") as! DetailViewController
                                    detailVC.titleEvent = itemSelected.title
                                    detailVC.staffEvent = itemSelected.staff
                                    detailVC.locationEvent = itemSelected.location
                                    detailVC.startEvent = itemSelected.starts
                                    detailVC.endEvent = itemSelected.ends
                                    detailVC.repeatEvent = itemSelected.rpeat
                                    detailVC.imageDetail = UIImage(data: data)!
                                    detailVC.descriptionDetail = itemSelected.description
                                    detailVC.secondPhotoEvent = UIImage(data: data1)!
                                    detailVC.key = itemSelected.key
                                    self.presentViewController(detailVC, animated: true, completion: nil)
                                }
                            })
                        }
                        else
                        {
                            print(error!.localizedDescription)
                        }

                    }}
            })
        }
        else
        {
            print(error!.localizedDescription)
        }

    }
}

}

1 个答案:

答案 0 :(得分:0)

您需要有条件地解包或无法合并这些值。强行打开你的方式是不安全的。

self.eventID = snapshot.value!["eventID"] as! String

应该是

eventID = snapshot.value?["eventID"] as? String ?? ""

不幸的是,编译器喜欢在遇到可选值时建议强制解包。这几乎总是一个可怕的建议。当你遇到时,你需要养成优雅地处理Optionals的习惯.None,因为Optionals是Swift语言中不可或缺的一部分。