My Question has to do with the sample code provided for Firebase. You can find it on Github or in the Documentation. Anyway, I don't really understand what the "deinit" on the database reference is doing. I read the deinit swift documentation here. I think I understand the purpose of using a deinit, but I'm not sure how it works in this case.
let kBannerAdUnitID = "ca-app-pub-3940256099942544/2934735716"
@objc(FCViewController)
class FCViewController: UIViewController, UITableViewDataSource, UITableViewDelegate,
UITextFieldDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate,
InviteDelegate {
// Instance variables
@IBOutlet weak var textField: UITextField!
@IBOutlet weak var sendButton: UIButton!
var ref: DatabaseReference!
var messages: [DataSnapshot]! = []
let posts = [Post]()
var msglength: NSNumber = 10
fileprivate var _refHandle: DatabaseHandle!
var storageRef: StorageReference!
var remoteConfig: RemoteConfig!
@IBOutlet weak var banner: GADBannerView!
@IBOutlet weak var clientTable: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
self.clientTable.register(UITableViewCell.self, forCellReuseIdentifier: "tableViewCell")
configureDatabase()
configureStorage()
configureRemoteConfig()
fetchConfig()
loadAd()
logViewLoaded()
}
deinit {
// NOT REALLY SURE WHAT THIS DOES
if let refHandle = _refHandle {
self.ref.child("messages").removeObserver(withHandle: _refHandle)
}
}
func configureDatabase() {
ref = Database.database().reference()
// Listen for new messages in the Firebase database
_refHandle = self.ref.child("messages").observe(.childAdded, with: { [weak self] (snapshot) -> Void in
guard let strongSelf = self else { return }
// EACH SNAPSHOT IS PLACED IN THE MESSAGES ARRAY
strongSelf.messages.append(snapshot)
// MAKE THE NUMBER OF ROWS IN THE FEED == THE NUMBER OF SNAPSHOTS
strongSelf.clientTable.insertRows(at: [IndexPath(row: strongSelf.messages.count-1, section: 0)], with: .automatic)
})
}
During initialization, your view controller adds a
childAdded
observer to a given Firebase database node. The passed in closure would still be called even after the view controller was long gone (i.e., deallocated). Firebase keeps a strong reference to it (and a weak reference to your view controller, by the way). This unnecessary calling might not be a major issue (yet!), but it's wrong nevertheless.The
deinit
code prevents that from happening.The deinitializer is called immediately before your view controller is deallocated. As such, it provides a nice place to remove that observer from the aforementioned database node. The observer (reference) is stored in the
_refHandle
property.By the way, you could simplify your observer removing code to:
you don't need to call
removeObserver
on the same node it was registered on.Weak View Controller. The
[weak self]
qualifier, in the aforementioned closure, is what specifies that Firebase should keep only a weak reference to your view controller. This is crucial to ensure that the view controller is properly released from memory when no longer needed. Without it, yourdeinit
would never be called!