geofire-objc icon indicating copy to clipboard operation
geofire-objc copied to clipboard

query observers seem to be retaining their keys somehow

Open andersryanc opened this issue 8 years ago • 0 comments

Inside a "manager" class, I'm creating two observers (one fore each .keyEntered and .keyExited) using a region query:

internal final class GeofireManager: NSObject {

    internal var locationsRef: FIRDatabaseReference = FIRDatabase.database().reference(withPath: FirebaseRoutes.locations)    
    internal var geoFire: GeoFire!

    weak var geofireDelegate: GeoFireRequestManagerDelegate!

    var regionQuery: GFRegionQuery?
    var regionKeyEntered: FirebaseHandle?
    var regionKeyExited: FirebaseHandle?

    // ...

    internal func setGeofireObserver(withRegion region: MKCoordinateRegion) {
        guard let gfd = self.geofireDelegate else { return }
        
        regionQuery = geoFire.query(with: region)
        
        regionKeyEntered = regionQuery!.observe(.keyEntered, with: { (key, location) in
            guard let currentKey: String = key else { return }
            let requestsRef: FIRDatabaseReference = FIRDatabase.database().reference(withPath: FirebaseRoutes.requests)
            requestsRef.child(currentKey).observeSingleEvent(of: .value, with: { (snapshot) in
                gfd.geofireAdded(snapshot: snapshot)
            })
        })
        
        regionKeyExited = regionQuery!.observe(.keyExited, with: { (key, location) in
            guard let currentKey: String = key else { return }
            gfd.geofireRemoved(key: currentKey)
        })
    }

    // ...

}

My delegate calls (gfd.geofireAdded(snapshot:) and gfd.geofireRemove(key: currentKey)) are working great... but during the lifecycle of my app from the viewController that is initializing this manager, I call the following function (and set the manager to nil) to remove the observers and deinit the manager class:

    internal func removeGeofireObservers() {
        if regionQuery != nil {
            if regionKeyEntered != nil {
                regionQuery?.removeObserver(withFirebaseHandle: regionKeyEntered!)
                regionKeyEntered = nil }
            
            if regionKeyExited != nil {
                regionQuery?.removeObserver(withFirebaseHandle: regionKeyExited!)
                regionKeyExited = nil }
            
            regionQuery?.removeAllObservers()
            regionQuery = nil
        }
        
        if circleQuery != nil {
            circleQuery?.removeAllObservers()
            circleQuery = nil
        }
    }

I've verified that the deinit {} method is called on the manager object and I would expect that the observers and all their data would have gone away in this process... but shortly later when I reinitialize the manager object and setup the observers again, none of the .keyEntered observers are fired UNLESS I move the map and update the region (at which point .keyExited is fired on all the items that were there before) and then move back and update to the previous region (at which point .keyEntered is fired again)...

Am I doing something wrong here? Why when I remove the observers and even deinit the parent class, does the data not totally refresh when I try it again at a later time?

andersryanc avatar Feb 02 '17 01:02 andersryanc