Collection 包含细分重复单元格的视图
Collection view with segment duplicate cells
我在使用 collection 视图和 segmentView 时遇到问题。
我有一个 viewController
,它有一个 segmentView 和 4 个元素 ( 0 => 所有,1 => 照片,2 => 音频, 3 => 视频 )
这是一个例子:
我有一个 collectionView 来显示数据取决于从 segmentController [=17] =]
它正在运行并显示数据,这是我的 collectionView 显示数据的方法
// MARK: Datasource collection method
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
// All Items
if segmentStatues == 0
{
let cellForAll = collectionView.dequeueReusableCell(withReuseIdentifier: "AllItemsCell", for: indexPath) as! AllItemsCollectionViewCell
// reset elements before declare
cellForAll.cellImage.image = nil
cellForAll.playBtn.isHidden = true
cellForAll.layer.borderWidth = 1
cellForAll.layer.borderColor = UIColor(red:0.93, green:0.93, blue:0.93, alpha:1.0).cgColor
// When type is an image
if sociaPosts[(indexPath as NSIndexPath).row].postType == "image"
{
cellForAll.cellImage.sd_setImage(with: URL(string: sociaPosts[(indexPath as NSIndexPath).row].postUrl))
}else if sociaPosts[(indexPath as NSIndexPath).row].postType == "audio"
{
cellForAll.cellImage.image = UIImage(named: "recorde_icon")
}else if sociaPosts[(indexPath as NSIndexPath).row].postType == "video"
{
cellForAll.cellImage.sd_setImage(with: URL(string: sociaPosts[(indexPath as NSIndexPath).row].thumbURL))
cellForAll.playBtn.isHidden = false
}
return cellForAll
}else{
// Cell if Images or videos or audios
let newCell = collectionView.dequeueReusableCell(withReuseIdentifier: "beepbeep", for: indexPath) as! userProfileImageCollectionViewCell
// If the type is images
if segmentStatues == 1
{
// Set image URL
newCell.cellImage.sd_setImage(with: URL(string: imagesPosts[(indexPath as NSIndexPath).row].postUrl))
// Get image likes and comments and shares
newCell.likeCount.text = String(imagesPosts[(indexPath as NSIndexPath).row].likes_count)
newCell.commentCount.text = String(imagesPosts[(indexPath as NSIndexPath).row].comments_count)
newCell.shareCount.text = String(imagesPosts[(indexPath as NSIndexPath).row].shares_count)
} else if segmentStatues == 3
{
// For Video player
var player = newCell.customVid
player = Bundle.main.loadNibNamed("VieoPlayer", owner: self, options: nil)?.last as? videoPlayer
player?.newIntitVideoPlayer(forViewController: self, videoURL: videosPosts[indexPath.row].postUrl , videoThumbnail: URL(string: videosPosts[indexPath.row].thumbURL), onReady: nil)
// Set video URL and Thumbnail
// Get video likes and comments and shares
newCell.likeCount.text = String(videosPosts[(indexPath as NSIndexPath).row].likes_count)
newCell.commentCount.text = String(videosPosts[(indexPath as NSIndexPath).row].comments_count)
newCell.shareCount.text = String(videosPosts[(indexPath as NSIndexPath).row].shares_count)
}else if segmentStatues == 2
{
// Audio player
let ad = Bundle.main.loadNibNamed("AudioPlayerView", owner: self, options: nil)?.last as! AudioPlayerView
ad.frame = CGRect(x: (newCell.contentView.frame.size.width - newCell.contentView.frame.size.height * 0.6) / 2, y: 20 , width: newCell.contentView.frame.size.height * 0.6, height: newCell.contentView.frame.size.height * 0.6)
ad.playImageView.image = nil
ad.tag = 6666
newCell.contentView.addSubview(ad)
// Set audio URL
ad.audioPath = URL(string: audiosPosts[indexPath.row].postUrl)
ad.viewInitialization()
// Get Audio likes and comments and shares
newCell.likeCount.text = String(audiosPosts[(indexPath as NSIndexPath).row].likes_count)
newCell.commentCount.text = String(audiosPosts[(indexPath as NSIndexPath).row].comments_count)
newCell.shareCount.text = String(audiosPosts[(indexPath as NSIndexPath).row].shares_count)
}
return newCell
}
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if self.segmentStatues == 0
{
return sociaPosts.count
}else if self.segmentStatues == 1
{
return imagesPosts.count
}else if self.segmentStatues == 2
{
return audiosPosts.count
}else
{
return videosPosts.count
}
}
我的 collection 视图中有 2 个自定义单元格,一个用于所有项目,另一个用于(图像 - 音频 - 视频)视图
我的问题是数据正在显示,但当我在 userProfileImageCollectionViewCell
中的段之间切换时单元格重复
这两张图片说明了问题
当我在音频段网中单击时显示所有音频单元格
但是当我点击像这样复制的图像或视频片段单元格后
仅在音频-图像-视频中发生**(userProfileImageCollectionViewCell)**
最后是我的 userProfileImageCollectionViewCell 代码:
已更新:
import UIKit
import SDWebImage
class userProfileImageCollectionViewCell: UICollectionViewCell {
@IBOutlet weak var customVid: videoPlayer!
@IBOutlet weak var cellImage: UIImageView!
@IBOutlet weak var likeButton: UIButton!
@IBOutlet weak var likeCount: UILabel!
@IBOutlet weak var commentButton: UIButton!
@IBOutlet weak var commentCount: UILabel!
@IBOutlet weak var shareButton: UIButton!
@IBOutlet weak var shareCount: UILabel!
override func prepareForReuse() {
cellImage.sd_setImage(with: nil)
self.customVid.subviews.forEach({ [=12=].removeFromSuperview() })
}
}
问题是 UICollectionViewCell
(顺便提一下 UITableViewCell
)被重复使用。
简单地说:
当您滚动时某个单元格从屏幕上消失时,它可能会在 top/bottom 处返回(根据滚动方向)。但它不是一个新的 "clean" 单元格,它是以前的单元格。这就是重用系统。
因此,当您这样做时:newCell.contentView.addSubview(ad)
您每次都添加了一个新的子视图,而没有检查是否已经存在。 juste 打桩的子视图。用 3D Hierarchy Debug of XCode.
很容易检查
既然你有一个userProfileImageCollectionViewCell
文件,最好的解决办法是使用prepareForReuse()
。
创建一个 IBOutlet
(我们称之为 customVid
),它将添加 ad/player 作为其子视图。
在 prepareForReuse()
中删除 customVid
的所有子视图。
在 collectionView:cellForRowAtIndexPath:
中,做这样的事情:
var player = Bundle.main.loadNibNamed("VieoPlayer", owner: self, options: nil)?.last as? videoPlayer
player?.newIntitVideoPlayer(forViewController: self, videoURL: videosPosts
newCell.customVid.addSubview(player)
为 ad
复制相同的机制(您可以使用相同的子视图,这取决于您)。
现在,一些与您的问题无关的建议:
以大写开头的 class 命名:userProfileImageCollectionViewCell
=> UserProfileImageCollectionViewCell
我会在 userProfileImageCollectionViewCell
中创建方法以使您的代码更具可读性。我不会说Swift,所以我的下一行代码可能无法编译,但你应该明白:
func fillWithVideo(videoParam video: CustomVideoClass) {
var player = newCell.customVid
player = Bundle.main.loadNibNamed("VieoPlayer", owner: self, options: nil)?.last as? videoPlayer
player?.newIntitVideoPlayer(forViewController: NOTself, videoURL: video.postUrl, videoThumbnail: URL(string: video.thumbURL), onReady: nil)
self.customVid.addSubview(player)
// Set video URL and Thumbnail
// Get video likes and comments and shares
self.likeCount.text = String(video.likes_count)
self.commentCount.text = String(video.comments_count)
self.shareCount.text = String(video.shares_count)
}
在collectionView:cellForRowAtIndexPath:
//If it's the correct section
let video = videosPosts[(indexPath as NSIndexPath).row] as CustomVideoClass
cell fillWithVideo(video)
请注意,您似乎使用了 UIViewController
,因此您可能想添加 UIViewController 参数以使 newIntitVideoPlayer()
方法起作用,但我不想放它在前面的例子中保持更简单。您可能需要替换以下行:
cell fillWithVideo(video andViewController:self)
和
func fillWithVideo(videoParam video: CustomVideoClass andViewController viewController: UIViewController)
player?.newIntitVideoPlayer(forViewController: viewController, videoURL: video.postUrl, videoThumbnail: URL(string: video.thumbURL), onReady: nil)
等对于每个部分的特定部分。它让你更容易阅读你在做什么。仅在 collectionView:cellForRowAtIndexPath:
中处理逻辑(哪个部分应该获取哪个项目等),其余部分交给可能适应的单元格。
我在使用 collection 视图和 segmentView 时遇到问题。
我有一个 viewController
,它有一个 segmentView 和 4 个元素 ( 0 => 所有,1 => 照片,2 => 音频, 3 => 视频 )
这是一个例子:
我有一个 collectionView 来显示数据取决于从 segmentController [=17] =]
它正在运行并显示数据,这是我的 collectionView 显示数据的方法
// MARK: Datasource collection method
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
// All Items
if segmentStatues == 0
{
let cellForAll = collectionView.dequeueReusableCell(withReuseIdentifier: "AllItemsCell", for: indexPath) as! AllItemsCollectionViewCell
// reset elements before declare
cellForAll.cellImage.image = nil
cellForAll.playBtn.isHidden = true
cellForAll.layer.borderWidth = 1
cellForAll.layer.borderColor = UIColor(red:0.93, green:0.93, blue:0.93, alpha:1.0).cgColor
// When type is an image
if sociaPosts[(indexPath as NSIndexPath).row].postType == "image"
{
cellForAll.cellImage.sd_setImage(with: URL(string: sociaPosts[(indexPath as NSIndexPath).row].postUrl))
}else if sociaPosts[(indexPath as NSIndexPath).row].postType == "audio"
{
cellForAll.cellImage.image = UIImage(named: "recorde_icon")
}else if sociaPosts[(indexPath as NSIndexPath).row].postType == "video"
{
cellForAll.cellImage.sd_setImage(with: URL(string: sociaPosts[(indexPath as NSIndexPath).row].thumbURL))
cellForAll.playBtn.isHidden = false
}
return cellForAll
}else{
// Cell if Images or videos or audios
let newCell = collectionView.dequeueReusableCell(withReuseIdentifier: "beepbeep", for: indexPath) as! userProfileImageCollectionViewCell
// If the type is images
if segmentStatues == 1
{
// Set image URL
newCell.cellImage.sd_setImage(with: URL(string: imagesPosts[(indexPath as NSIndexPath).row].postUrl))
// Get image likes and comments and shares
newCell.likeCount.text = String(imagesPosts[(indexPath as NSIndexPath).row].likes_count)
newCell.commentCount.text = String(imagesPosts[(indexPath as NSIndexPath).row].comments_count)
newCell.shareCount.text = String(imagesPosts[(indexPath as NSIndexPath).row].shares_count)
} else if segmentStatues == 3
{
// For Video player
var player = newCell.customVid
player = Bundle.main.loadNibNamed("VieoPlayer", owner: self, options: nil)?.last as? videoPlayer
player?.newIntitVideoPlayer(forViewController: self, videoURL: videosPosts[indexPath.row].postUrl , videoThumbnail: URL(string: videosPosts[indexPath.row].thumbURL), onReady: nil)
// Set video URL and Thumbnail
// Get video likes and comments and shares
newCell.likeCount.text = String(videosPosts[(indexPath as NSIndexPath).row].likes_count)
newCell.commentCount.text = String(videosPosts[(indexPath as NSIndexPath).row].comments_count)
newCell.shareCount.text = String(videosPosts[(indexPath as NSIndexPath).row].shares_count)
}else if segmentStatues == 2
{
// Audio player
let ad = Bundle.main.loadNibNamed("AudioPlayerView", owner: self, options: nil)?.last as! AudioPlayerView
ad.frame = CGRect(x: (newCell.contentView.frame.size.width - newCell.contentView.frame.size.height * 0.6) / 2, y: 20 , width: newCell.contentView.frame.size.height * 0.6, height: newCell.contentView.frame.size.height * 0.6)
ad.playImageView.image = nil
ad.tag = 6666
newCell.contentView.addSubview(ad)
// Set audio URL
ad.audioPath = URL(string: audiosPosts[indexPath.row].postUrl)
ad.viewInitialization()
// Get Audio likes and comments and shares
newCell.likeCount.text = String(audiosPosts[(indexPath as NSIndexPath).row].likes_count)
newCell.commentCount.text = String(audiosPosts[(indexPath as NSIndexPath).row].comments_count)
newCell.shareCount.text = String(audiosPosts[(indexPath as NSIndexPath).row].shares_count)
}
return newCell
}
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if self.segmentStatues == 0
{
return sociaPosts.count
}else if self.segmentStatues == 1
{
return imagesPosts.count
}else if self.segmentStatues == 2
{
return audiosPosts.count
}else
{
return videosPosts.count
}
}
我的 collection 视图中有 2 个自定义单元格,一个用于所有项目,另一个用于(图像 - 音频 - 视频)视图
我的问题是数据正在显示,但当我在 userProfileImageCollectionViewCell
中的段之间切换时单元格重复这两张图片说明了问题
当我在音频段网中单击时显示所有音频单元格
但是当我点击像这样复制的图像或视频片段单元格后
仅在音频-图像-视频中发生**(userProfileImageCollectionViewCell)**
最后是我的 userProfileImageCollectionViewCell 代码:
已更新:
import UIKit
import SDWebImage
class userProfileImageCollectionViewCell: UICollectionViewCell {
@IBOutlet weak var customVid: videoPlayer!
@IBOutlet weak var cellImage: UIImageView!
@IBOutlet weak var likeButton: UIButton!
@IBOutlet weak var likeCount: UILabel!
@IBOutlet weak var commentButton: UIButton!
@IBOutlet weak var commentCount: UILabel!
@IBOutlet weak var shareButton: UIButton!
@IBOutlet weak var shareCount: UILabel!
override func prepareForReuse() {
cellImage.sd_setImage(with: nil)
self.customVid.subviews.forEach({ [=12=].removeFromSuperview() })
}
}
问题是 UICollectionViewCell
(顺便提一下 UITableViewCell
)被重复使用。
简单地说: 当您滚动时某个单元格从屏幕上消失时,它可能会在 top/bottom 处返回(根据滚动方向)。但它不是一个新的 "clean" 单元格,它是以前的单元格。这就是重用系统。
因此,当您这样做时:newCell.contentView.addSubview(ad)
您每次都添加了一个新的子视图,而没有检查是否已经存在。 juste 打桩的子视图。用 3D Hierarchy Debug of XCode.
既然你有一个userProfileImageCollectionViewCell
文件,最好的解决办法是使用prepareForReuse()
。
创建一个 IBOutlet
(我们称之为 customVid
),它将添加 ad/player 作为其子视图。
在 prepareForReuse()
中删除 customVid
的所有子视图。
在 collectionView:cellForRowAtIndexPath:
中,做这样的事情:
var player = Bundle.main.loadNibNamed("VieoPlayer", owner: self, options: nil)?.last as? videoPlayer
player?.newIntitVideoPlayer(forViewController: self, videoURL: videosPosts
newCell.customVid.addSubview(player)
为 ad
复制相同的机制(您可以使用相同的子视图,这取决于您)。
现在,一些与您的问题无关的建议:
以大写开头的 class 命名:userProfileImageCollectionViewCell
=> UserProfileImageCollectionViewCell
我会在 userProfileImageCollectionViewCell
中创建方法以使您的代码更具可读性。我不会说Swift,所以我的下一行代码可能无法编译,但你应该明白:
func fillWithVideo(videoParam video: CustomVideoClass) {
var player = newCell.customVid
player = Bundle.main.loadNibNamed("VieoPlayer", owner: self, options: nil)?.last as? videoPlayer
player?.newIntitVideoPlayer(forViewController: NOTself, videoURL: video.postUrl, videoThumbnail: URL(string: video.thumbURL), onReady: nil)
self.customVid.addSubview(player)
// Set video URL and Thumbnail
// Get video likes and comments and shares
self.likeCount.text = String(video.likes_count)
self.commentCount.text = String(video.comments_count)
self.shareCount.text = String(video.shares_count)
}
在collectionView:cellForRowAtIndexPath:
//If it's the correct section
let video = videosPosts[(indexPath as NSIndexPath).row] as CustomVideoClass
cell fillWithVideo(video)
请注意,您似乎使用了 UIViewController
,因此您可能想添加 UIViewController 参数以使 newIntitVideoPlayer()
方法起作用,但我不想放它在前面的例子中保持更简单。您可能需要替换以下行:
cell fillWithVideo(video andViewController:self)
和
func fillWithVideo(videoParam video: CustomVideoClass andViewController viewController: UIViewController)
player?.newIntitVideoPlayer(forViewController: viewController, videoURL: video.postUrl, videoThumbnail: URL(string: video.thumbURL), onReady: nil)
等对于每个部分的特定部分。它让你更容易阅读你在做什么。仅在 collectionView:cellForRowAtIndexPath:
中处理逻辑(哪个部分应该获取哪个项目等),其余部分交给可能适应的单元格。