The app crashes when adding new keys in firestore

时间:2017-12-18 06:57:16

标签: ios swift xcode google-cloud-firestore

I made a test application following the example of Google with github, but with a few changes (less keys used in the firestore and less filters).

The problem is this, the app crashing when I added new keys in the firestore, but the app works with two keys previously added.

Crashes and shows error on fatalError("error"). I can not understand why with two keys the application works, but if i begin to use the third key (hall) then the app crashes.

What could be the problem?

It's my code:

class ViewControllerTwo: UIViewController, UITableViewDelegate, UITableViewDataSource {

    @IBOutlet var tableView: UITableView!

    private var sweets: [Sweet] = []
    private var document: [DocumentSnapshot] = []

    fileprivate var query: Query? {
        didSet {
            if let listener = listener {
                listener.remove()
            }
        }
    }

    private var listener: FIRListenerRegistration?

    fileprivate func observeQuery() {

        guard let query = query else { return }

        stopObserving()

        listener = query.addSnapshotListener { [unowned self] (snapshot, error) in

            guard let snapshot = snapshot else {

                print("Error fetching snapshot results: \(error!)")

                return

            }

            let models = snapshot.documents.map { (document) -> Sweet in

                if let model = Sweet(dictionary: document.data()) {

                    return model

                } else {

                    fatalError("error")

                }

            }

            self.sweets = models

            self.document = snapshot.documents

            self.tableView.reloadData()

        }

    }

    @IBAction func filterButton(_ sender: Any) {
        present(filters.navigationController, animated: true, completion: nil)    
    }

    lazy private var filters: (navigationController: UINavigationController, filtersController: FilterViewController) = {
        return FilterViewController.fromStoryboard(delegate: self)
    }()

    fileprivate func stopObserving() {
        listener?.remove()
    }

    fileprivate func baseQuery() -> Query {
        return Firestore.firestore().collection("sweets").limit(to: 50)    
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        query = baseQuery()    
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(true)

        observeQuery()
    }

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(true)

        stopObserving()    
    }

    deinit {
        listener?.remove()    
    }

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

        return sweets.count
    }

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

        let sweet = sweets[indexPath.row]

        cell.studioNameLabel.text = sweet.name
        cell.studioAddressLabel.text = sweet.content
        cell.hallNameLabel.text = sweet.hall

        return cell

    }

}

extension ViewControllerTwo: FiltersViewControllerDelegate {

    func query(withCategory title: String?) -> Query {

        var filtered = baseQuery()

        if let title = title, !title.isEmpty {
            filtered = filtered.whereField("title", isEqualTo: title)
        }

        return filtered
    }

    func controller(_ controller: FilterViewController, didSelectCategory title: String?) {

        let filtered = query(withCategory: title)

        self.query = filtered
        observeQuery()

    }
}

class ViewControllerCell: UITableViewCell {

    @IBOutlet weak var studioNameLabel: UILabel!
    @IBOutlet weak var studioAddressLabel: UILabel!
    @IBOutlet weak var hallNameLabel: UILabel!

}

And my struct:

protocol DocumentSerializable  {
    init?(dictionary:[String:Any])
}
struct Sweet {
    var name:String
    var content:String
    var hall:String
    var dictionary:[String:Any] {
        return [
            "name": name,
            "content" : content,
            "hall" : hall
        ]
    }
}
extension Sweet : DocumentSerializable {

    static let title = [
        "one",
        "two",
        "three",
        "four"
    ]
    init?(dictionary: [String : Any]) {
        guard let name = dictionary["name"] as? String,
            let content = dictionary["content"] as? String,
            let hall = dictionary["hall"] as? String else { return nil }

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

My project in google drive

google drive

google service info.plist

1 个答案:

答案 0 :(得分:0)

You just need to reinstall app once you add any new key to you existing structure.

So you should decide before structure implementation that what keys you will need. Or you can reinstall app if you add new key in future.