UICollectionView 重新加载单元格但不删除旧单元格
UICollectionView Reloading cells but not deleting old ones
我一直在尝试实现一个集合视图,用户可以在其中点赞 post 但出于某种原因,当用户这样做时,它会更新提要,但只是将单元格数量加倍并留下应该消失的旧细胞。简而言之,一半的单元格被更新,另一半是旧值。基本上我无法弄清楚如何简单地更新当前单元格而不会出现问题。理想情况下,我希望用户按下“赞”按钮,除了该按钮转向 "Unlike" 并且 post 上的赞数在 collectionview 中发生更改外,不会发生其他任何事情。
这是加载集合视图单元格的代码:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = feedCollectionView.dequeueReusableCell(withReuseIdentifier: cellIdentifier, for: indexPath) as! MyGroupFeedCollectionViewCell
cell.postKey = feedArray[indexPath.row].postKey
//clears the cells first
cell.profileImage.image = nil
cell.usernameLabel.text = nil
cell.usernameLabel2.text = nil
cell.groupName.text = nil
cell.postImageView.image = nil
cell.postCaptionTextView.text = nil
cell.timeStamp.text = nil
//load profile picture
cell.profileImage.sd_setImage(with: URL(string: feedArray[indexPath.row].ProfilePic), placeholderImage: UIImage(named:"no profile picture.png"))
//load username
cell.usernameLabel.text = feedArray[indexPath.row].Username
cell.usernameLabel2.text = feedArray[indexPath.row].Username
//load groupName when in home feed
cell.groupName.text = feedArray[indexPath.row].GroupName
//load postImage
cell.postImageView.sd_setImage(with: URL(string: feedArray[indexPath.row].PostImage), placeholderImage: UIImage(named:"penguinPanorama"))
//load caption
cell.postCaptionTextView.text = feedArray[indexPath.row].caption
//load likes once likes are implemented
//checks if the user has liked the post or not
databaseRef.child("likes").child((FIRAuth.auth()?.currentUser?.uid)!).child(feedArray[indexPath.row].postKey).observe(.value, with: { (snapshot) in
if(snapshot.exists())
{
cell.liked = "Yes"
cell.likeButton.setTitle("Unlike", for: .normal)
}
else{
cell.liked = "No"
cell.likeButton.setTitle("Like", for: .normal)
}
})
下面是按下赞按钮的函数代码:
@IBAction func likeButton_tapped(_ sender: Any) {
self.likeButton.isEnabled = false
print(self.postKey)
print(self.liked)
//make it so liking or unliking adds or subtracts from the total number of likes on the post
if liked == "Yes"
{
self.databaseRef.child("likes").child((FIRAuth.auth()?.currentUser?.uid)!).child(self.postKey).removeValue()
let NewLikeNumber = likeNumber - 1
self.databaseRef.child("GroupPosts").child(self.groupName.text!).child(self.postKey).child("likes").setValue(NewLikeNumber)
print(NewLikeNumber)
}
else{
self.databaseRef.child("likes").child((FIRAuth.auth()?.currentUser?.uid)!).child(self.postKey).setValue("")
let NewLikeNumber = likeNumber + 1
self.databaseRef.child("GroupPosts").child(self.groupName.text!).child(self.postKey).child("likes").setValue(NewLikeNumber)
print(NewLikeNumber)
}
self.likeButton.isEnabled = true
}
对于点赞,我建议您使用 Firebase 交易,因为您的点赞计数可能会因为并发修改而变得一团糟:
func likePost(_ post: Post, completion: @escaping () -> ()) {
guard let currentUserId = Auth.auth().currentUser?.uid else {
return
}
databaseRef.child(likes).child(currentUserId).child(postKey).runTransactionBlock ( { (currentData: MutableData) -> TransactionResult in
if var data = currentData.value as? [String: Any] {
var count = data["likesCount"] as! Int
count += 1
data["likesCount"] = count
currentData.value = data
return TransactionResult.success(withValue: currentData)
}
return TransactionResult.success(withValue: currentData)
}, andCompletionBlock: { (error, success, snapshot) in
// ...
})
}
当然,不喜欢 post 的用户也是如此。
现在要知道用户是否喜欢 post,您可以在 class 中创建一个布尔值以在本地保存喜欢的状态:
private var isPostLiked = false
每当用户点击“赞”按钮时,就做一个简单的检查:
func handleLikeTapped() {
guard let post = post else {
return
}
if isPostLiked {
NetworkManager.shared.likePost(post, completion: { [weak self] in
// Once the completion handler of your method is called, the likes count in your database is now updated.
// To avoid making another read in the database just now, you can just
// Update your count (a label that shows how many likes a specific post received I guess ?) locally here so that the user can see in realtime the change (with animation or not depending on what you want to achieve)
// And finally update the like state of the post so that if the user click again on like it wouldn't mess everything up:
self?.isPostLiked = false
})
}
else {
NetworkManager.shared.dislikePost(post, completion: { [weak self] in
// ...
})
}
}
当然,以后如果您需要在不同的视图控制器中访问点赞数,您只需使用 observeSingleEvent(of: .value)
从数据库中获取更新的点赞数。
如果您有任何问题,请告诉我!
我一直在尝试实现一个集合视图,用户可以在其中点赞 post 但出于某种原因,当用户这样做时,它会更新提要,但只是将单元格数量加倍并留下应该消失的旧细胞。简而言之,一半的单元格被更新,另一半是旧值。基本上我无法弄清楚如何简单地更新当前单元格而不会出现问题。理想情况下,我希望用户按下“赞”按钮,除了该按钮转向 "Unlike" 并且 post 上的赞数在 collectionview 中发生更改外,不会发生其他任何事情。
这是加载集合视图单元格的代码:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = feedCollectionView.dequeueReusableCell(withReuseIdentifier: cellIdentifier, for: indexPath) as! MyGroupFeedCollectionViewCell
cell.postKey = feedArray[indexPath.row].postKey
//clears the cells first
cell.profileImage.image = nil
cell.usernameLabel.text = nil
cell.usernameLabel2.text = nil
cell.groupName.text = nil
cell.postImageView.image = nil
cell.postCaptionTextView.text = nil
cell.timeStamp.text = nil
//load profile picture
cell.profileImage.sd_setImage(with: URL(string: feedArray[indexPath.row].ProfilePic), placeholderImage: UIImage(named:"no profile picture.png"))
//load username
cell.usernameLabel.text = feedArray[indexPath.row].Username
cell.usernameLabel2.text = feedArray[indexPath.row].Username
//load groupName when in home feed
cell.groupName.text = feedArray[indexPath.row].GroupName
//load postImage
cell.postImageView.sd_setImage(with: URL(string: feedArray[indexPath.row].PostImage), placeholderImage: UIImage(named:"penguinPanorama"))
//load caption
cell.postCaptionTextView.text = feedArray[indexPath.row].caption
//load likes once likes are implemented
//checks if the user has liked the post or not
databaseRef.child("likes").child((FIRAuth.auth()?.currentUser?.uid)!).child(feedArray[indexPath.row].postKey).observe(.value, with: { (snapshot) in
if(snapshot.exists())
{
cell.liked = "Yes"
cell.likeButton.setTitle("Unlike", for: .normal)
}
else{
cell.liked = "No"
cell.likeButton.setTitle("Like", for: .normal)
}
})
下面是按下赞按钮的函数代码:
@IBAction func likeButton_tapped(_ sender: Any) {
self.likeButton.isEnabled = false
print(self.postKey)
print(self.liked)
//make it so liking or unliking adds or subtracts from the total number of likes on the post
if liked == "Yes"
{
self.databaseRef.child("likes").child((FIRAuth.auth()?.currentUser?.uid)!).child(self.postKey).removeValue()
let NewLikeNumber = likeNumber - 1
self.databaseRef.child("GroupPosts").child(self.groupName.text!).child(self.postKey).child("likes").setValue(NewLikeNumber)
print(NewLikeNumber)
}
else{
self.databaseRef.child("likes").child((FIRAuth.auth()?.currentUser?.uid)!).child(self.postKey).setValue("")
let NewLikeNumber = likeNumber + 1
self.databaseRef.child("GroupPosts").child(self.groupName.text!).child(self.postKey).child("likes").setValue(NewLikeNumber)
print(NewLikeNumber)
}
self.likeButton.isEnabled = true
}
对于点赞,我建议您使用 Firebase 交易,因为您的点赞计数可能会因为并发修改而变得一团糟:
func likePost(_ post: Post, completion: @escaping () -> ()) {
guard let currentUserId = Auth.auth().currentUser?.uid else {
return
}
databaseRef.child(likes).child(currentUserId).child(postKey).runTransactionBlock ( { (currentData: MutableData) -> TransactionResult in
if var data = currentData.value as? [String: Any] {
var count = data["likesCount"] as! Int
count += 1
data["likesCount"] = count
currentData.value = data
return TransactionResult.success(withValue: currentData)
}
return TransactionResult.success(withValue: currentData)
}, andCompletionBlock: { (error, success, snapshot) in
// ...
})
}
当然,不喜欢 post 的用户也是如此。
现在要知道用户是否喜欢 post,您可以在 class 中创建一个布尔值以在本地保存喜欢的状态:
private var isPostLiked = false
每当用户点击“赞”按钮时,就做一个简单的检查:
func handleLikeTapped() {
guard let post = post else {
return
}
if isPostLiked {
NetworkManager.shared.likePost(post, completion: { [weak self] in
// Once the completion handler of your method is called, the likes count in your database is now updated.
// To avoid making another read in the database just now, you can just
// Update your count (a label that shows how many likes a specific post received I guess ?) locally here so that the user can see in realtime the change (with animation or not depending on what you want to achieve)
// And finally update the like state of the post so that if the user click again on like it wouldn't mess everything up:
self?.isPostLiked = false
})
}
else {
NetworkManager.shared.dislikePost(post, completion: { [weak self] in
// ...
})
}
}
当然,以后如果您需要在不同的视图控制器中访问点赞数,您只需使用 observeSingleEvent(of: .value)
从数据库中获取更新的点赞数。
如果您有任何问题,请告诉我!