以编程方式在特定的UICollectionViewCell内创建TableView?

8
我正在尝试在UICollectionViewCell中添加一个TableView,因此我想从TableView中自己管理该单元格。 更明确地说,如果indexPath.row为2,则我想调用我的tableView单元格内的collectionView indexPath.row。 请查看图片,我已经用红色标出了我想要做的事情。 我使用UICollectionViewController和UICollectionViewControllerFlowLayout以编程方式创建了所有内容。


这个截图中UICollectionView在哪里? - luk2302
屏幕上全部都是UICollectionView,即使它看起来不像CollectionView。 - Labinot Bajrami
4个回答

8

对于那些需要它的人,我找到了解决方案:

class CustomizedCell: UICollectionViewCell, UITableViewDataSource, UITableViewDelegate {

    var tableView = UITableView()
    let cellIdentifier: String = "tableCell"

    override func layoutSubviews() {
        super.layoutSubviews()

        tableView.delegate = self
        tableView.dataSource = self

        tableView.register(UITableViewCell.self, forCellReuseIdentifier: cellIdentifier)
    }

    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 4
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.value1, reuseIdentifier: cellIdentifier)

        cell.textLabel?.text = "1 CUP"
        cell.detailTextLabel?.text = "Whole"

        return cell
    }
}

然后在CollectionView的viewDidLoad方法中,我做了以下操作:

collectionView?.register(CustomizedCell.self, forCellWithReuseIdentifier: "cell")

在UICollectionView的cellForItemAtIndexPath方法中,我这样调用:
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CustomizedCell

    return cell
}

我没有看到你何时将UITableview添加到集合单元格中? - skymook
3
这是否违反了MVC模式?因为单元格不应该了解任何关于数据的信息,因为它们只是视图。 - Tigran Iskandaryan
只有在使用MVC时才是这样,我猜。 :^) - Ruiz
那么你如何将数据分配给不同集合单元格中的表视图? - user3390652
@b-m-gevariya 你是如何在CollectionView和TableView的单元格高度中进行选择的? - Vaibhav Jhaveri

3
您可以为该indexpath创建自定义UICollectionView单元格,并在单元格xib中添加一个tableview。
在自定义单元格类中实现tableview的委托方法。
 class CustomCollectionViewCell: UICollectionViewCell, UITableViewDataSource, UITableViewDelegate
  {
    @IBOutlet var tableView: UITableView!

    override func layoutSubviews() 
    {
        super.layoutSubviews()
        tableView.delegate = self
        tableView.dataSource = self
    }
  }

这个实现能够继承CollectionViewCell本身的索引吗?还是我需要通过CollectionViewDelegate协议来获取它? - user3390652

0

我找到了一个对我有效的解决方案。

import UIKit

class FirstCollectionViewCell: UICollectionViewCell {
    
    let cellId = "cellId"
    
    let tableView:UITableView = {
        let tableView = UITableView()
        tableView.translatesAutoresizingMaskIntoConstraints = false
        return tableView
    }()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        backgroundColor = .blue
        
        addSubview(tableView)
        setUpViews()
        addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[v0]|", options: NSLayoutFormatOptions(), metrics: nil, views: ["v0":tableView]))
        addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[v0]|", options: NSLayoutFormatOptions(), metrics: nil, views: ["v0":tableView]))
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init is not done")
    }
    
    func setUpViews() {
        tableView.delegate = self
        tableView.dataSource = self
        tableView.register(MyCell.self, forCellReuseIdentifier: cellId) 
    }
}

extension FirstCollectionViewCell: UITableViewDataSource, UITableViewDelegate {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 5
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath) as! MyCell
        cell.label.text = "Testing testing"
        return cell
    }
    
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return 40.0
    }
}

class MyCell:UITableViewCell {
    override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        setUpViews()
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    // creating a label to display some dummy text
    let label:UILabel = {
        let label = UILabel()
        label.text = "test"
        label.textAlignment = .center
        label.translatesAutoresizingMaskIntoConstraints = false
        return label
    }()
    
    func setUpViews() {
        addSubview(label)
        addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[v0]|", options: NSLayoutFormatOptions(), metrics: nil, views: ["v0":label]))
        addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[v0]|", options: NSLayoutFormatOptions(), metrics: nil, views: ["v0":label]))
    }
}

如果表格视图单元格具有动态高度,该怎么办? - Alok

0

上述方法在MVC模式下效果不佳。我建议创建一个NSObject子类,该子类符合UITableViewDelegate和UITableViewDataSource协议。

例如:

class DataProvider: NSObject, UITableViewDelegate, UITableViewDataSource {
    
    let dataManager = DataManager()
    let reuseId = "Cell"
    
    //MARK: - DataSource Methods
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return dataManager.data.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: reuseId, for: indexPath)
        cell.backgroundColor = .yellow
        return cell
    }
    
    //MARK: - Delegate Methods
    
}

现在在您的UICollectionViewCell子类中,您可以指定tableView数据源和委托属性,如下所示:

class ContainerCollectionViewCell: UICollectionViewCell {

    @IBOutlet weak var label: UILabel!
    @IBOutlet weak var collectionView: UICollectionView!
    
    let dataProvider = DataProvider()
    
    let tableView: UITableView = {
        let table = UITableView()
        table.translatesAutoresizingMaskIntoConstraints = false
        return table
    }()
    
    override func awakeFromNib() {
       super.awakeFromNib()
        
        addSubview(tableView)
        tableView.fillSuperview()
        tableView.register(UITableViewCell.self, forCellReuseIdentifier: dataProvider.reuseId)
        tableView.delegate = dataProvider
        tableView.dataSource = dataProvider
    }
}

也许不完美,但比上面的答案实现了更好的封装性。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接