我有2个选项卡一个的TabBar控制器:塔巴含有ClassA和塔布含有ClassB的。我将数据发送到tabA/ClassA中的Firebase数据库,然后观察tabB/ClassB中的数据库,并将其检索到并添加到tableView中。在tableView的单元格内,我显示了当前在数据库中的运动鞋的数量。斯威夫特的iOS荧光灯,如何刷新的TableView外火力地堡观察.childAdded过滤掉重复值?
我知道.observeSingleEvent(.value)
VS .observe(.childAdded)
之间的差异。我需要实时更新,因为当数据在塔巴得到发送,如果我切换到塔布,我想看到新的数据会添加到的tableView一次塔巴/ ClassA的完成。
在ClassB的,我有我的viewWillAppear中的观察者。我把它放在一个pullDataFromFirebase()
函数中,每次出现视图时函数都会运行。我也有Notification观察者,它监听要在tabA/ClassA中发送的数据,以便它更新tableView。通知事件再次运行pullDataFromFirebase()
在ClassA中,调用Firebase的回调函数内部我有通知帖子来运行ClassB中的pullDataFromFirebase()
函数。
我遇到的问题是,如果我在塔布,而新的数据更新,它完成时,显示的数据的单元格具有计数和计数揭去。我对它进行了调试,包含数据的sneakerModels数组有时会复制并重复新添加的数据。
例如,如果我在B类和有2个双球鞋在数据库中,pullDataFromFirebase()
FUNC将运行,并且的tableView细胞会显示“您有2双运动鞋”
发生了什么是,如果我切换到塔巴/ ClassA的,然后加1双球鞋,而它的更新,我切换到塔布/ ClassB的,细胞仍然会说:“你有2个双运动鞋”,但那么,一旦更新了电池会说:“你有5双运动鞋“和5个细胞会出现?如果我切换标签并回来,它会正确显示“你有3双运动鞋”和正确数量的细胞。
这就是通知的来源。一旦我补充说,如果我经历了同样的过程,并开始使用2个运动鞋,那么细胞会说“你有两双运动鞋”,我去tabA,再加一双,开关回到tabB,仍然看到“你有两双运动鞋”。一旦数据被发送的小区将简要介绍“你有5双运动鞋”并显示5个细胞,然后将正确地更新为“你有3双运动鞋”和细胞的正确的量(我没得切换标签)。
通知似乎工作,但有这短暂的瞬间不正确。
我做了一些研究,我能找到的最多的是一些表示我需要使用信号量的帖子,但显然来自几个人,他们在下面留下评论,他们说信号量不是意味着异步使用。 我不得不更新我的问题以排除信号参考。
现在,我在pullDataFromFirebase的完成处理程序运行tableView.reloadData()()。
如何重新加载的tableView观察员之外,一旦它的完成,以防止重复值?
型号:
class SneakerModel{
var sneakerName:String?
}
塔布/ ClassB的:
ClassB: UIViewController, UITableViewDataSource, UITableViewDelegate{
var sneakerModels[SneakerModel]
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(pullDataFromFirebase), name: NSNotification.Name(rawValue: "pullFirebaseData"), object: nil)
}
override func viewWillAppear(_ animated: Bool){
super.viewWillAppear(animated)
pullDataFromFirebase()
}
func pullDataFromFirebase(){
sneakerRef?.observe(.childAdded, with: {
(snapshot) in
if let dict = snapshot.value as? [String:Any]{
let sneakerName = dict["sneakerName"] as? String
let sneakerModel = SneakerModel()
sneakerModel.sneakerName = sneakerName
self.sneakerModels.append(sneakerModel)
//firebase runs on main queue
self.tableView.reloadData()
}
})
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return sneakerModels.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "SneakerCell", for: indexPath) as! SneakerCell
let name = sneakerModels[indePath.row]
//I do something else with the sneakerName and how pairs of each I have
cell.sneakerCount = "You have \(sneakerModels.count) pairs of sneakers"
return cell
}
}
}
塔巴/ ClassA的:
ClassA : UIViewController{
@IBAction fileprivate func postTapped(_ sender: UIButton) {
dict = [String:Any]()
dict.updateValue("Adidas", forKey: "sneakerName")
sneakerRef.?.updateChildValues(dict, withCompletionBlock: {
(error, ref) in
//1. show alert everything was successful
//2. post notification to ClassB to update tableView
NotificationCenter.default.post(name: Notification.Name(rawValue: "pullFirebaseData"), object: nil)
}
}
}
基本上不要使用信号量来解决异步数据处理问题。是否可以选择发布通知并在通知的接收者中运行异步代码('updateChildValues')?或者在通知中传递添加的对象并更新数据源数组而不重新*拉数据。 – vadian
@vadian感谢您的帮助。那不是我在做什么?该帖子以ClassA发送,接收者为ClassB。 updateChildValues是在ClassB中的pullFirebaseData函数中运行的。为什么不将信号量用于异步进程? –
有一个正确的方式来异步做东西。信号量不是它。 – matt