问题
I have a tableView with several cells (created by MVVM-architecture).
In ViewController I fill my tableView like this:
tbv.registerCells(
withModels:
FirstViewModel.self,
SecondViewModel.self,
ThirdViewModel.self)
My task is to put my TableView in one cell of CollectionView. I thought l have to create CollectionView in my ViewController, after it create CollectionViewCell and CollectionCellViewModel, but how to do it exactly I don't understand.
If you know, how to make it, help.
回答1:
How I have several tableviews in collection views in one of my apps. First I have a view controller in which I build my collection view. As usually proposed in the new design guidelines, I have the Collection View delegate and data source in an extension of this view controller.
In your view controller you define a delegate and data source for your table view. Preferably, this is a different class. I would not have the tableview data source and delegate also in the same view controller as your collection view.
class WorkoutSettingsViewController: UIViewController, LoadWorkoutSettings {
//MARK: - Properties
//Used variables
//Used constants
private let settingsDelegate = SettingsTableViewDelegate()
The extension would then look like this.
extension WorkoutSettingsViewController: UICollectionViewDataSource, UICollectionViewDelegate {
func numberOfSections(in collectionView: UICollectionView) -> Int {
//Whatever sets your sections
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
//Whatever sets your rows per section
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Workout Settings", for: indexPath) as! SettingsCollectionViewCell
settingsDelegate.workoutTitleLabel = [countdown, mainView, spokenMessage]
settingsDelegate.mainContentLabel = getSettingsContent()
cell.settingsTableView.delegate = settingsDelegate
cell.settingsTableView.dataSource = settingsDelegate
cell.settingsTableView.reloadData()
return cell
}
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
//Whatever you need as header or footer
}
The delegate does exactly what you would like the table view data source and delegate to do.
class SettingsTableViewDelegate: NSObject, UITableViewDataSource, UITableViewDelegate {
//MARK: - Properties
//Used variables
var workoutTitleLabel = [String]()
var mainContentLabel = [String]()
var selectedSetting: ((Int) -> ())? = .none
private var secondaryContentLabel = [String]()
//Used constants
private let onTitle = NSLocalizedString("ON", comment: "Localized on title")
private let offTitle = NSLocalizedString("OFF", comment: "Localized off title")
private let fontColorBlack = UIColor(red: 20.0/255.0, green: 20.0/255.0, blue: 19.0/255.0, alpha: 1.0)
private let fontColorRed = UIColor(red: 255.0/255.0, green: 96.0/255.0, blue: 89.0/255.0, alpha: 1.0)
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
workoutTitleLabel.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Settings Cell") as! WorkoutTableViewCell
cell.workoutTitle.text = workoutTitleLabel[indexPath.row]
cell.mainContent.text = mainContentLabel[indexPath.row]
cell.secondaryContent.text = ""
(mainContentLabel[indexPath.row] == offTitle) ? (cell.mainContent.textColor = fontColorRed) : (cell.mainContent.textColor = fontColorBlack)
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
selectedSetting?(indexPath.row)
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
61
}
}
Your collection view cell should look like this.
class SettingsCollectionViewCell: UICollectionViewCell {
@IBOutlet weak var settingsTableView: UITableView!
}
This should then work. If you need to have a callback from the table view delegate / data source to your view controller managing your collection view, you can use a closure. In the example table view delegate the closure is called selectedSettings. In your view controller in viewDidLoad you define the call back for instance like this:
override func viewDidLoad() {
super.viewDidLoad()
settingsDelegate.selectedSetting = { [unowned self] selection in
startSettingsMenu(for: selection)
}
}
The result looks like this.
Kind regards, MacUserT
回答2:
In Tableview each row you can load UITableViewCell with pass collectionviewdata
//View Controller
var collectionView1Data = ["cell1", "cell2"]
var collectionView2Data = ["cell1", "cell2"]
//UITableviewDelegate Datasource
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
//.....
if indexPath.row == 1 {
let cell = tableView.dequeueReusableCell(withIdentifier: "CellID") as? TableviewCell
cell.collectionData = collectionView1Data /// Collectionviewdata
return cell
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: "CellID") as? TableviewCell
cell.collectionData = collectionView2Data
return cell
}
}
==============================
Each Tableviewcell contains CollectionView
//UITableViewCell
class TableviewCell: UITableViewCell {
@IBOutlet weak var collectionView: UICollectionView!
var collectionData: [String]? {
didSet {
guard collectionData != nil else {
return
}
collectionView.reloadData()
}
}
override func awakeFromNib() {
super.awakeFromNib()
collectionView.register(UINib(nibName: "collectionViewCell", bundle: nil), forCellWithReuseIdentifier: "collectionViewCell")
collectionView.dataSource = self
collectionView.delegate = self
}
}
extension TableviewCell: UICollectionViewDataSource, UICollectionViewDelegate,UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
collectionData.count ?? 0
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionViewCell", for: indexPath) as? collectionViewCell
cell...
return cell
}
}
来源:https://stackoverflow.com/questions/65937087/how-can-l-put-tableview-inside-collectionviewcell