Error when trying to make another query on Firestore

I have an that has 2 buttons.

  • When I press the search button the app goes to a tableview with my firestore data and a searchBar.
  • When I press the Query button I query my database based on Array.

The problem is that when I press the Query button and my query is done, if I go back and press the search button my app crashes with the following error.

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'FIRESTORE INTERNAL ASSERTION FAILED: Firestore instance has already been started and its settings can no longer be changed. You can only set settings before calling any other methods on a Firestore instance.'
*** First throw call stack:
(0x1d95ed27c 0x1d87c79f8 0x1d9506988 0x1da016ee8 0x1050f2f7c 0x104f0aaa4 0x104f1be30 0x104e0cba4 0x104e0a6a8 0x104e0ab78 0x205949fc8 0x20594a3cc 0x2058a74c8 0x2058bb4b8 0x2058bc8e0 0x20589faf0 0x20638aed0 0x1ddaa1a20 0x1ddaa69c8 0x1dda092d0 0x1dda37330 0x1dda37f20 0x1d957e5f8 0x1d9579320 0x1d957989c 0x1d95790b0 0x1db77979c 0x205ef3978 0x104e22e58 0x1d903e8e0)
libc++abi.dylib: terminating with uncaught exception of type NSException

I searched a lot about this issue and I can't understand what it means. If anyone need code of course tell me to edit, but I don't think code is relevant. I think its more general error.

EDIT

Some code from my search button which I use batches.

func  beginBatchFetch() {

        let settings = FirestoreSettings()
        settings.isPersistenceEnabled = false

        fetchMoreIngredients = true
        let db = Firestore.firestore()
        db.settings = settings

        var query: Query!

        if ingredientsArray.isEmpty {
            SVProgressHUD.show()

            query = db.collection("Ingredients").limit(to: 4)
            print("First 4 ingredient loaded")
        } else {
            query = db.collection("Ingredients").start(afterDocument: lastDocument).limit(to: 4)
            print("Next 4 ingredient loaded")
        }

        query.getDocuments { (querySnapshot, err) in
            if let err = err {
                print("\(err.localizedDescription)")
                print("Test Error")
            } else if querySnapshot!.isEmpty {
                self.fetchMoreIngredients = false
                return
            } else {
                if (querySnapshot!.isEmpty == false){
                    let res = querySnapshot!.documents.compactMap({Ingredients(dictionary: $0.data())})
                    self.ingredientsArray.append(contentsOf: res)

                    self.tableView.reloadData()
                    self.fetchMoreIngredients = false
                    SVProgressHUD.dismiss()
                }

                self.lastDocument = querySnapshot!.documents.last
            }
        }
    }

    func searchIngredients(text: String){

        fetchMoreIngredients = true

        let db = Firestore.firestore()

        db.collection("Ingredients").whereField("compName", arrayContains: text).getDocuments{ (querySnapshot, err) in
            if let err = err {
                print("\(err.localizedDescription)")
                print("Test Error")
            } else {
                if (querySnapshot!.isEmpty == false){
                    self.searchedIngredientsArray = querySnapshot!.documents.compactMap({Ingredients(dictionary: $0.data())})
                    self.ingredientsArray = self.searchedIngredientsArray
                    self.tableView.reloadData()
                    self.fetchMoreIngredients = true

                }else{
                    print("No Ingredients were found")
                }
            }
        }

    }

1 answer

  • answered 2019-06-17 14:34 Frank van Puffelen

    You're enabling the local cache for Firestore with this code:

    let settings = FirestoreSettings()
    settings.isPersistenceEnabled = false
    
    let db = Firestore.firestore()
    db.settings = settings
    

    This should only be done once for the entire run for the application, while you seem to be doing it multiple times.

    The usual solution is to move this code into your AppDelegate, so that it follows the lifecycle of your application. But since local persistence is enabled by default for Firestore on iOS, you can also simply remove this code and get the same behavior.