我正在尝试将 CollectionView
与 TableView
结合起来,所以除了一个我无法自己解决的问题之外,一切正常。
我必须在CollectionViews
中加载一些数据,这些数据按照CollectionView所在的TableViewCell
的标题进行排序。由于某种原因,每次启动应用程序时,前三个 TableViewCells
都是相同的。如果我垂直滚动一点,它们就会更改为正确的数据。
但也可能会发生这样的情况:在使用它时,有时会显示与另一个 TableViewCell
上的 TableViewCell
相同的数据,如果我稍微滚动一下,问题就会再次得到解决。
我认为问题出在可重用单元上,但我自己找不到错误。我尝试插入一个colletionView.reloadData()
并在重用之前将单元格设置为nil
,遗憾的是这不起作用。
我的TableViewController
import UIKit
import RealmSwift
import Alamofire
import SwiftyJSON
let myGroupLive = DispatchGroup()
let myGroupCommunity = DispatchGroup()
var channelTitle=""
class HomeVTwoTableViewController: UITableViewController {
var headers = ["LIVE","Channel1", "Channel2", "Channel3", "Channel4", "Channel5", "Channel6"]
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(_ animated: Bool) {
self.navigationController?.navigationBar.isTranslucent = false
DataController().fetchDataLive(mode: "get")
DataController().fetchDataCommunity(mode: "get")
}
//MARK: Custom Tableview Headers
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return headers[section]
}
//MARK: DataSource Methods
override func numberOfSections(in tableView: UITableView) -> Int {
return headers.count
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
//Choosing the responsible PrototypCell for the Sections
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.section == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellBig", for: indexPath) as! HomeVTwoTableViewCell
print("TableViewreloadMain")
cell.collectionView.reloadData()
return cell
}
else if indexPath.section >= 1 {
// getting header Titel for reuse in cell
channelTitle = self.tableView(tableView, titleForHeaderInSection: indexPath.section)!
let cell = tableView.dequeueReusableCell(withIdentifier: "cellSmall", for: indexPath) as! HomeVTwoTableViewCellSmall
// anti Duplicate protection
cell.collectionView.reloadData()
return cell
}
else {
channelTitle = self.tableView(tableView, titleForHeaderInSection: indexPath.section)!
let cell = tableView.dequeueReusableCell(withIdentifier: "cellSmall", for: indexPath) as! HomeVTwoTableViewCellSmall
// anti Duplicate protection
cell.collectionView.reloadData()
return cell
}
}
}
}
我的TableViewCell
与`CollectionView
import UIKit
import RealmSwift
var communities: Results<Community>?
class HomeVTwoTableViewCellSmall: UITableViewCell{
//serves as a translator from ChannelName to the ChannelId
var channelOverview: [String:String] = ["Channel1": "399", "Channel2": "401", "Channel3": "360", "Channel4": "322", "Channel5": "385", "Channel6": "4"]
//Initiaize the CellChannel Container
var cellChannel: Results<Community>!
//Initialize the translated ChannelId
var channelId: String = ""
@IBOutlet weak var collectionView: UICollectionView!
}
extension HomeVTwoTableViewCellSmall: UICollectionViewDataSource,UICollectionViewDelegate {
//MARK: Datasource Methods
func numberOfSections(in collectionView: UICollectionView) -> Int
{
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
{
return (cellChannel.count)
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
{
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionCellSmall", for: indexPath) as? HomeVTwoCollectionViewCellSmall else
{
fatalError("Cell has wrong type")
}
//removes the old image and Titel
cell.imageView.image = nil
cell.titleLbl.text = nil
//inserting the channel specific data
let url : String = (cellChannel[indexPath.row].pictureId)
let name :String = (cellChannel[indexPath.row].communityName)
cell.titleLbl.text = name
cell.imageView.downloadedFrom(link :"link")
return cell
}
//MARK: Delegate Methods
override func layoutSubviews() {
myGroupCommunity.notify(queue: DispatchQueue.main, execute: {
let realm = try! Realm()
//Getting the ChannelId from Dictionary
self.channelId = self.channelOverview[channelTitle]!
//load data from Realm into variables
self.cellChannel = realm.objects(Community.self).filter("channelId = \(String(describing: self.channelId)) ")
self.collectionView.dataSource = self
self.collectionView.delegate = self
print("collectionView layout Subviews")
self.collectionView.reloadData()
})
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
selectedCommunity = (cellChannel[indexPath.row].communityId)
let home = HomeViewController()
home.showCommunityDetail()
}
}
提前致谢。
最佳答案
tl;dr 将 channelTitle
设为单元格上的变量,而不是全局变量。另外,请在 prepareForReuse
我在这里可能弄错了,但是您在创建单元格后是否在单元格上设置了channelTitle
?正如我所看到的,在你的 viewController 中,你根据标题创建单元格,并且对于每个单元格,你将 TableViewController
的 channelTitle
设置为给定部分的标题。
如果是这种情况,那么 TableViewCell
实际上没有收到任何有关在调用 reloadData()
之前应加载内容的信息。
一般来说,我还建议在您的 HomeVTwoTableViewCellSmall
中实现 prepareForReuse
,因为它让您有机会清理任何过时的数据。您可能希望在该方法中将 cellChannel
和 channelId
设置为空字符串或 nil
之类的操作,因此当重复使用旧单元格时数据一直存在。
另外,我刚刚重新阅读了您的单元格代码,看起来您正在 layoutSubviews
中进行一些关键的初始单元格设置。该方法可能会被多次调用,但实际上您只需要调用它一次(对于它所做的大部分工作)。试试这个:
- 使用单元上的重用标识符覆盖 init
- 在该 init 中,添加
self.collectionView.dataSource = self
和self.collectionView.delegate = self
- 在
channelTitle
上添加didSet
- 在 viewController 中设置
channelTitle
所以代码看起来像:
var channelTitle: String = "" {
didSet {
self.channelId = self.channelOverview[channelTitle]!
self.cellChannel = realm.objects(Community.self).filter("channelId = \(String(describing: self.channelId)) ")
self.collectionView.reloadData()
}
}
这样,您仅在单元格更新为新 channel 时才重新加载数据,而不是单元格 View 的每个布局。
<小时/>抱歉...还有一个补充。我不知道您的 channelTitle
实际上是如何传递的。正如我所看到的,您使用 channelTitle 作为全局变量而不是本地变量。不要那样做!在实现上述代码之前,从当前位置删除 channelTitle
。您会看到一些错误,因为您在 ViewController 中设置它并在单元格中访问它。您想要的是从 ViewController 设置单元格上的 channelTitle
(正如我上面概述的那样)。这也解释了为什么您在所有三个单元格中看到相同的数据。基本上,您只设置了一个 channelTitle
,并且所有三个单元格都在寻找该全局值来获取其数据。
希望对您有一点帮助!
(此外,您应该能够删除 cellForRowAtIndexPath
方法中的 else if
block ,因为它后面的 else
block 覆盖了相同的代码。您还可以删除 viewDidLoad,因为它没有执行任何操作,并且通常您应该查看是否可以删除任何 !
,因为它们不安全. 使用 ?
或 guard
或 if let
代替)
关于ios - TableView中的CollectionView显示错误的Data swift,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44757530/