Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Detach from Firestore listener

I'm using Firestore together with Swift.

I have a singleton data class UserManager. I call this from my different ViewControllers to get data to populate my tableviews. I want the tableviews to automatically update when the collections are updated so I need to use a SnapshotListener. Everything works fine but I'm not sure how to detach from the listener when the Viewcontroller is closed.

In the singleton class I have methods like this below. The method gives a list of users and will be called from several different places around my app.

I also want to give back a reference to the listener so that I can detach from it when the Viewcontroller is closed. But I can't get it working. The below solution gives compiler error.

I've been trying to look at the reference, for example here https://firebase.google.com/docs/firestore/query-data/listen but I need to get it working when the data is loaded in a singleton class instead of directly in the Viewcontroller. What is the way to go here?

In UserManager:

func allUsers(completion:@escaping ([User], ListenerRegistration?)->Void) {
    let listener = db.collection("users").addSnapshotListener { querySnapshot, error in
        if let documents = querySnapshot?.documents {
            var users = [User]()
            for document in documents {
                let user = User(snapshot: document)
                users.append(user)
            }
            completion(users, listener)
        }
    }
}

In ViewController:

override func viewDidLoad() {
    super.viewDidLoad()
    UserManager.shared.allUsers(completion: { (users, listener) in
        self.users = users
        self.listener = listener
        self.tableView.reloadData()
    })
}

deinit {
    self.listener.remove()
}
like image 246
Martin Avatar asked Dec 23 '22 06:12

Martin


1 Answers

I guess the compiler error that you see is referring to the fact that you are using listener into it's own defining context.

Try this for a change:

In UserManager:

func allUsers(completion:@escaping ([User])->Void) -> ListenerRegistration? {
    return db.collection("users").addSnapshotListener { querySnapshot, error in
        if let documents = querySnapshot?.documents {
            var users = [User]()
            for document in documents {
                let user = User(snapshot: document)
                users.append(user)
            }
            completion(users)
        }
    }
}

In ViewController:

override func viewDidLoad() {
    super.viewDidLoad()
    self.listener = UserManager.shared.allUsers(completion: { (users) in
        self.users = users
        self.tableView.reloadData()
    })
}

deinit {
    self.listener.remove()
}
like image 129
Mihai Fratu Avatar answered Dec 29 '22 10:12

Mihai Fratu