在 Swift 中使用 Firebase 中的句柄删除观察者
Remove the observer using the handle in Firebase in Swift
我有以下案例。根控制器是 UITabViewController
。有一个ProfileViewController
,我在里面做了一个观察者,用户开始成为朋友(然后屏幕功能发生变化)。 ProfileViewController
5个选项卡中有4个可以打开,所以当前用户可以在四个地方用同一个用户打开屏幕。之前的版本,当ProfileViewController在一个地方打开时,我在deinit中删除了观察者,然后ref.removeAllObservers()
就删除了,现在用户情况是这样的,我开始在viewDidDisappear中使用handle和delete observer。我想演示一下代码,看看它是否可以改进,以及我在这种情况下是否做对了。
我在 viewWillAppear 中调用这个函数
fileprivate func firObserve(_ isObserve: Bool) {
guard let _user = user else { return }
FIRFriendsDatabaseManager.shared.observeSpecificUserFriendshipStart(observer: self, isObserve: isObserve, userID: _user.id, success: { [weak self] (friendModel) in
}) { (error) in
}
}
这是在 FIRFriendsDatabaseManager
fileprivate var observeSpecificUserFriendshipStartDict = [AnyHashable : UInt]()
func observeSpecificUserFriendshipStart(observer: Any, isObserve: Bool, userID: String, success: ((_ friendModel: FriendModel) -> Void)?, fail: ((_ error: Error) -> Void)?) {
let realmManager = RealmManager()
guard let currentUserID = realmManager.getCurrentUser()?.id else { return }
DispatchQueue.global(qos: .background).async {
let specificUserFriendRef = Database.database().reference().child(MainGateways.friends.description).child(currentUserID).child(SubGateways.userFriends.description).queryOrdered(byChild: "friendID").queryEqual(toValue: userID)
if !isObserve {
guard let observerHashable = observer as? AnyHashable else { return }
if let handle = self.observeSpecificUserFriendshipStartDict[observerHashable] {
self.observeSpecificUserFriendshipStartDict[observerHashable] = nil
specificUserFriendRef.removeObserver(withHandle: handle)
debugPrint("removed handle", handle)
}
return
}
var handle: UInt = 0
handle = specificUserFriendRef.observe(.childAdded, with: { (snapshot) in
if snapshot.value is NSNull {
return
}
guard let dict = snapshot.value as? [String : Any] else { return }
guard let friendModel = Mapper<FriendModel>().map(JSON: dict) else { return }
if friendModel.friendID == userID {
success?(friendModel)
}
}, withCancel: { (error) in
fail?(error)
})
guard let observerHashable = observer as? AnyHashable else { return }
self.observeSpecificUserFriendshipStartDict[observerHashable] = handle
}
}
关于维护对每个 viewController 的引用的实现,我会考虑将逻辑移动到 viewController 本身的扩展。
如果您想避免像以前那样调用 ref.removeAllObservers()
,并假设每个 viewController 只有一个侦听器。我会让 listener ref 成为视图控制器上的一个变量。
这样,所有内容都包含在 viewController 中。如果其他类型的 viewControllers 将执行类似类型的听众管理,它也可能是创建协议的良好候选者。
我有以下案例。根控制器是 UITabViewController
。有一个ProfileViewController
,我在里面做了一个观察者,用户开始成为朋友(然后屏幕功能发生变化)。 ProfileViewController
5个选项卡中有4个可以打开,所以当前用户可以在四个地方用同一个用户打开屏幕。之前的版本,当ProfileViewController在一个地方打开时,我在deinit中删除了观察者,然后ref.removeAllObservers()
就删除了,现在用户情况是这样的,我开始在viewDidDisappear中使用handle和delete observer。我想演示一下代码,看看它是否可以改进,以及我在这种情况下是否做对了。
我在 viewWillAppear 中调用这个函数
fileprivate func firObserve(_ isObserve: Bool) {
guard let _user = user else { return }
FIRFriendsDatabaseManager.shared.observeSpecificUserFriendshipStart(observer: self, isObserve: isObserve, userID: _user.id, success: { [weak self] (friendModel) in
}) { (error) in
}
}
这是在 FIRFriendsDatabaseManager
fileprivate var observeSpecificUserFriendshipStartDict = [AnyHashable : UInt]()
func observeSpecificUserFriendshipStart(observer: Any, isObserve: Bool, userID: String, success: ((_ friendModel: FriendModel) -> Void)?, fail: ((_ error: Error) -> Void)?) {
let realmManager = RealmManager()
guard let currentUserID = realmManager.getCurrentUser()?.id else { return }
DispatchQueue.global(qos: .background).async {
let specificUserFriendRef = Database.database().reference().child(MainGateways.friends.description).child(currentUserID).child(SubGateways.userFriends.description).queryOrdered(byChild: "friendID").queryEqual(toValue: userID)
if !isObserve {
guard let observerHashable = observer as? AnyHashable else { return }
if let handle = self.observeSpecificUserFriendshipStartDict[observerHashable] {
self.observeSpecificUserFriendshipStartDict[observerHashable] = nil
specificUserFriendRef.removeObserver(withHandle: handle)
debugPrint("removed handle", handle)
}
return
}
var handle: UInt = 0
handle = specificUserFriendRef.observe(.childAdded, with: { (snapshot) in
if snapshot.value is NSNull {
return
}
guard let dict = snapshot.value as? [String : Any] else { return }
guard let friendModel = Mapper<FriendModel>().map(JSON: dict) else { return }
if friendModel.friendID == userID {
success?(friendModel)
}
}, withCancel: { (error) in
fail?(error)
})
guard let observerHashable = observer as? AnyHashable else { return }
self.observeSpecificUserFriendshipStartDict[observerHashable] = handle
}
}
关于维护对每个 viewController 的引用的实现,我会考虑将逻辑移动到 viewController 本身的扩展。
如果您想避免像以前那样调用 ref.removeAllObservers()
,并假设每个 viewController 只有一个侦听器。我会让 listener ref 成为视图控制器上的一个变量。
这样,所有内容都包含在 viewController 中。如果其他类型的 viewControllers 将执行类似类型的听众管理,它也可能是创建协议的良好候选者。