我试图将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()
}
}
提前致谢。
答案 0 :(得分:0)
tl; dr使channelTitle
成为您单元格上的变量,而不是全局变量。另外,在prepareForReuse
我可能会在这里弄错,但是你创建它们后是否在单元格上设置了channelTitle
?正如我所看到的,在viewController中,您可以根据标题创建单元格,并为每个单元格设置TableViewController
的{{1}}作为给定部分的标题。
如果是这种情况,那么在您致电channelTitle
之前,TableViewCell
实际上没有收到任何有关它应该加载的信息。
一般情况下,我还建议您在reloadData()
中实施prepareForReuse
,因为它会让您有机会清理任何过时的数据。可能你会想要设置HomeVTwoTableViewCellSmall
和cellChannel
之类的东西来清空该方法中的字符串或channelId
,所以当重复使用该单元时,旧数据会一直存在。
另外,我只是重新阅读了您拥有的单元格代码,看起来您正在nil
中进行一些关键的初始单元设置。该方法可能会被大量调用,但实际上只需要调用一次(对于它所做的大部分工作)。试试这个:
layoutSubviews
和self.collectionView.dataSource = self
self.collectionView.delegate = self
didSet
channelTitle
所以代码看起来像:
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()
}
}
实际上是如何通过的。在我看来,你将channelTitle用作全局变量而不是本地变量。不要那样做!在实现上述代码之前,从当前的位置删除channelTitle
。您将看到一些错误,因为您在ViewController中设置它并在单元格中访问它。你想要的是从ViewController设置单元格channelTitle
(如上所述)。这也解释了为什么你在所有三个单元格中看到相同的数据。基本上你只设置了一个channelTitle
,所有三个单元格都在寻找那个全局值来获取它们的数据。
希望有所帮助!
(另外,您应该可以删除channelTitle
方法中的else if
块,因为其后面的cellForRowAtIndexPath
块包含相同的代码。您还可以删除viewDidLoad ,因为它没有做任何事情,你应该通常看看你是否可以摆脱任何else
因为它们不安全。使用!
或?
或guard
代替