Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios Xcode:为什么在展开时我的可选值为nill?_Ios_Swift_Firebase_Google Cloud Firestore - Fatal编程技术网

Ios Xcode:为什么在展开时我的可选值为nill?

Ios Xcode:为什么在展开时我的可选值为nill?,ios,swift,firebase,google-cloud-firestore,Ios,Swift,Firebase,Google Cloud Firestore,有人可以看看我的代码,告诉我为什么我的值是零。如果你需要我发布其他文件,我会的。该项目主要是firebase,每当您试图在应用程序中发布时,应用程序就会崩溃。我相信当屏幕必须更新时,它会崩溃,因为数据正在访问数据库 import UIKit import FirebaseFirestore class FeedVC: UITableViewController { var db = Firestore.firestore() var postArray = [Posts]

有人可以看看我的代码,告诉我为什么我的值是零。如果你需要我发布其他文件,我会的。该项目主要是firebase,每当您试图在应用程序中发布时,应用程序就会崩溃。我相信当屏幕必须更新时,它会崩溃,因为数据正在访问数据库

import UIKit
import FirebaseFirestore

class FeedVC: UITableViewController {



    var db = Firestore.firestore()
    var postArray = [Posts]()

    override func viewDidLoad() {
        super.viewDidLoad()

        //db = Firestore.firestore()
//loadData()
      // checkForUpdates()


    }
       override func viewDidAppear(_ animated: Bool){
        loadData()
        checkForUpdates()


    }

    func loadData() {
        db.collection("posts").getDocuments() {
            querySnapshot, error in
            if let error = error {
                print("\(error.localizedDescription)")
            }else{
                self.postArray = querySnapshot!.documents.flatMap({Posts(dictionary: $0.data())})
                DispatchQueue.main.async {
                    self.tableView.reloadData()
                }
            }
        }


    }

    func checkForUpdates() {
        db.collection("posts").whereField("timeStamp", isGreaterThan: Date())
            .addSnapshotListener {
                querySnapshot, error in

                guard let snapshot = querySnapshot else {return}

                snapshot.documentChanges.forEach {
                    diff in

                    if diff.type == .added {
                        self.postArray.append(Posts(dictionary: diff.document.data())!)
                        DispatchQueue.main.async {
                            self.tableView.reloadData()
                        }
                    }
                }

        }
    }

    @IBAction func composePost(_ sender: Any) {






        let composeAlert = UIAlertController(title: "New Post", message: "Enter your name and message", preferredStyle: .alert)

        composeAlert.addTextField { (textField:UITextField) in
            textField.placeholder = "Your name"
        }

        composeAlert.addTextField { (textField:UITextField) in
            textField.placeholder = "Your message"
        }

        composeAlert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))

        composeAlert.addAction(UIAlertAction(title: "Send", style: .default, handler: { (action:UIAlertAction) in

            if let name = composeAlert.textFields?.first?.text, let content = composeAlert.textFields?.last?.text {

                let newSweet = Posts(name: name, content: content, timeStamp: Date())

                var ref:DocumentReference? = nil
                ref = self.db.collection("posts").addDocument(data: newSweet.dictionary) {
                    error in

                    if let error = error {
                        print("Error adding document: \(error.localizedDescription)")
                    }else{
                        print("Document added with ID: \(ref!.documentID)")
                    }

                }

            }

        }))

        self.present(composeAlert, animated: true, completion: nil)


    }



    // MARK: - Table view data source
    override func numberOfSections(in tableView: UITableView) -> Int {

        return 0
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

        return postArray.count
    }


    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)

        let sweet = postArray[indexPath.row]

        cell.textLabel?.text = "\(sweet.name): \(sweet.content)"
        cell.detailTextLabel?.text = "\(sweet.timeStamp)"

        return cell
    }
  }

import Foundation
import FirebaseFirestore

protocol DocumentSerializable  {
    init?(dictionary:[String:Any])
}


struct Posts {
    var name:String
    var content:String
    var timeStamp:Date

    var dictionary:[String:Any] {
        return [
            "name":name,
            "content" : content,
            "timeStamp" : timeStamp
        ]
    }

}

extension Posts : DocumentSerializable {
    init?(dictionary: [String : Any]) {
        guard let name = dictionary["name"] as? String,
            let content = dictionary["content"] as? String,
            let timeStamp = dictionary ["timeStamp"] as? Date else {return nil}

        self.init(name: name, content: content, timeStamp: timeStamp)
    }
}






使用
时间戳
代替
日期

 import FirebaseFirestore 
    guard let stamp = data["timeStamp"] as? Timestamp else { return nil }


根据评论,这条线正在崩溃

self.postArray.append(Posts(dictionary: diff.document.data())!)
它崩溃了,因为你正在强制展开一个为零的变量

Posts(dictionary: diff.document.data())! <- ! means 'I guarantee you will never be nil'
这里有令人不快的代码

guard 
   let name = dictionary["name"] as? String,
   let content = dictionary["content"] as? String,
   let timeStamp = dictionary ["timeStamp"] as? Date 

else {return nil} //OFFENDING CODE!
如果字典中不存在这些变量中的任何一个,它将失败,并返回nil

所以。。。您的一个文档不包含这些字段之一

您还可以参考Firestore指南了解如何编写日期。查看中的示例代码


此外,Firestore没有内部日期类型,因此请改用Timestamp.dateValue。在此处查看它

它崩溃可能是因为您正在更新viewDidLoad下的表视图数据。我也应该将其移动到何处?崩溃发生在-self.postArray.append(Posts(dictionary:diff.document.data())!)上,请使用ViewWillDisplay或ViewDidDisplay进行尝试。我在ViewWillDisplay和ViewDidDisplay中进行了尝试,但仍然出现错误。
guard 
   let name = dictionary["name"] as? String,
   let content = dictionary["content"] as? String,
   let timeStamp = dictionary ["timeStamp"] as? Date 

else {return nil} //OFFENDING CODE!