deinit 到底在做什么?为什么?
What exactly is deinit doing here? And why?
我的问题与为 Firebase 提供的示例代码有关。您可以在 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 上找到它。我想我理解使用 deinit 的目的,但我不确定在这种情况下它是如何工作的。
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)
})
}
在初始化期间,您的视图控制器会向给定的 Firebase 数据库节点添加一个 childAdded
观察器。传入的闭包在视图控制器早已消失(即释放)后仍将被称为 even。 Firebase 保留了对它的 strong 引用(顺便说一句,还有对视图控制器的 weak 引用)。这种不必要的调用可能不是一个主要问题(现在!),但它仍然是错误的。
deinit
代码阻止了这种情况的发生。
deinitializer 在您的视图控制器被释放之前立即被调用。因此,它提供了一个从上述数据库节点中 删除 该观察者的好地方。观察者(参考)存储在 _refHandle
属性 中。
顺便说一下,您可以将观察者删除的代码简化为:
if let refHandle = _refHandle {
self.ref.removeObserver(withHandle: _refHandle)
}
您不需要在相同的节点上调用removeObserver
。
弱视图控制器。在上述闭包中, [weak self]
限定符指定 Firebase 应仅保留对视图控制器的弱引用。这对于确保视图控制器在不再需要时从内存中正确释放至关重要。没有它,您的 deinit
将永远不会被调用!
我的问题与为 Firebase 提供的示例代码有关。您可以在 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 上找到它。我想我理解使用 deinit 的目的,但我不确定在这种情况下它是如何工作的。
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)
})
}
在初始化期间,您的视图控制器会向给定的 Firebase 数据库节点添加一个 childAdded
观察器。传入的闭包在视图控制器早已消失(即释放)后仍将被称为 even。 Firebase 保留了对它的 strong 引用(顺便说一句,还有对视图控制器的 weak 引用)。这种不必要的调用可能不是一个主要问题(现在!),但它仍然是错误的。
deinit
代码阻止了这种情况的发生。
deinitializer 在您的视图控制器被释放之前立即被调用。因此,它提供了一个从上述数据库节点中 删除 该观察者的好地方。观察者(参考)存储在 _refHandle
属性 中。
顺便说一下,您可以将观察者删除的代码简化为:
if let refHandle = _refHandle {
self.ref.removeObserver(withHandle: _refHandle)
}
您不需要在相同的节点上调用removeObserver
。
弱视图控制器。在上述闭包中, [weak self]
限定符指定 Firebase 应仅保留对视图控制器的弱引用。这对于确保视图控制器在不再需要时从内存中正确释放至关重要。没有它,您的 deinit
将永远不会被调用!