self.dismiss(animated: true, completion: nil)
返回带有表视图的视图控制器,但是该表视图(一旦用户回到表视图)就显示出重复行,但在Firebase中成功删除了该子项,并创建了一个新的子项-但是tableview显示的是未被删除两次的子项。
这是VC1中的所有相关代码:
class PostMessageListViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
@IBOutlet weak var table: UITableView!
var topicID:namePosts?
let currentUserID = Auth.auth().currentUser?.uid
var posts = [Post]()
lazy var refresher: UIRefreshControl = {
let refreshControl = UIRefreshControl()
refreshControl.tintColor = .white
refreshControl.addTarget(self, action: #selector(requestData), for: .valueChanged)
return refreshControl
}()
@objc
func requestData() {
self.table.reloadData()
refresher.endRefreshing()
}
func reloadData(){
table.reloadData()
}
override func viewDidLoad() {
super.viewDidLoad()
self.table.separatorStyle = UITableViewCellSeparatorStyle.none
table.refreshControl = refresher
//DataManager.shared.firstVC = self
self.table.delegate = self
self.table.dataSource = self
let postCell = UINib(nibName: "PostTableViewCell", bundle: nil)
self.table.register(postCell, forCellReuseIdentifier: "cell")
self.posts.removeAll()
Database.database().reference().child("posts").child(postID!.name)
.observe(.childAdded) { (snap) in
if snap.exists() {
//declare some values here...
self.posts.append( //some values here)
self.posts.sort(by: {$0.createdAt > $1.createdAt})
self.table.reloadData()
})
}
else {
self.table.reloadData()
}
}
//observe if a post is deleted by user
Database.database().reference().child("posts").child("posts").observe(.childRemoved) { (snapshot) in
let postToDelete = self.indexOfPosts(snapshot: snapshot)
self.posts.remove(at: postToDelete)
self.table.reloadData()
//self.table.deleteRows(at: [NSIndexPath(row: questionToDelete, section: 1) as IndexPath], with: UITableViewRowAnimation.automatic)
//self.posts.remove(at: indexPath.row)
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.posts.count
}
func indexOfPosts(snapshot: DataSnapshot) -> Int {
var index = 0
for post in self.posts {
if (snapshot.key == post.postID) {
return index
}
index += 1
}
return -1
}
编辑:忘了说了,但是我在另一个Viewcontroller中使用了此代码,并且在那儿工作正常。但是,我只是将代码从该代码复制到了此代码,并删除了一堆我不需要的东西,但是我似乎找不到在此代码中缺少的东西。
答案 0 :(得分:0)
这可能不是 答案,但可能会导致 答案。如注释中所述,有两个数组用于管理tableView的dataSource。一个包含数据,另一个包含使用索引技术-我相信这可能会导致问题,如问题中所述。
另一个问题是,当每个子项都被初始添加时,我们会对数组进行重新排序,然后刷新tableView-这可能会导致延迟和闪烁。 (闪烁=不好)
因此,让我们建立一些基础。首先是一个拥有职位的班级
PostClass {
var post_id = ""
var post_text = ""
var creation_date = ""
}
第二个Firebase结构类似
posts
post_id_0
text: "the first post"
timestamp: "20190220"
post_id_1
text: "the second post"
timestamp: "20190221"
然后是一些技巧,以填充数据源并保留一个添加了子级的观察者。这一点很重要,因为您不想一直刷新每个孩子的tableView,因为它可能(会)闪烁。因此,我们利用childAdded事件始终位于.value事件之前,以便填充数组,然后.value将刷新一次,然后每次之后更新tableView。这是一些代码-正在进行很多工作,因此逐步进行。
var postsArray = [String]()
var initialLoad = true
func ReadPosts() {
let postsRef = self.ref.child("posts").queryOrdered(byChild: "timestamp")
postsRef.observe(.childAdded, with: { snapshot in
let aPost = PostClass()
aPost.post_id = snapshot.key
aPost.post_text = snapshot.childSnapshot("text").value as! String
aPost.creation_date = snapshot.childSnapshot("timestamp").value as! String
self.postsArray.append(aPost)
//upon first load, don't reload the tableView until all children are loaded
if ( self.initialLoad == false ) {
self.postsTableView.reloadData()
}
})
//when a child is removed, the event will contain that child snapshot
// we locate the child node via it's key within the array and remove it
// then reload the tableView
postsRef.observe(.childRemoved, with: { snapshot in
let keyToRemove = snapshot.key
let i = self.postsArray.index(where: { $0.post_id == keyToRemove})
self.postsArray.remove(at: i)
self.postsTableView.reloadData()
})
//this event will fire *after* all of the child nodes were loaded
// in the .childAdded observer. So children are sorted, added and then
// the tableView is refreshed. Set initialLoad to false so the next childAdded
// after the initial load will refresh accordingly.
postsRef.observeSingleEvent(of: .value, with: { snapshot in
self.postsTableView.reloadData()
self.initialLoad = false
})
}
注意事项
我们让Firebase进行繁重的工作,并按creation_date排序节点,以便它们井然有序。
这可以通过viewDidLoad调用,我们首先将initialLoad
类var设置为true