【问题标题】:How to push view controller on a button tap in nested collection view cell swift如何在嵌套集合视图单元格中快速按下按钮点击视图控制器
【发布时间】:2021-12-11 10:52:40
【问题描述】:

我在表格视图中有一个集合视图,在集合视图单元格中有一个按钮。按下该按钮时,我想按下另一个 vc。

我尝试在集合视图单元格中创建一个委托,但集合视图单元格在表格单元格中有一个 cellforitem 方法,因此无法在主视图控制器中声明委托。

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
    
    var tableView: UITableView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .black
        
        setUpTableView()
    }
    
    func setUpTableView() {
        let tableView = UITableView()
        
        view.addSubview(tableView)
        
        tableView.register(
            HomeRecommendStoreTableViewCell.self,
            forCellReuseIdentifier: HomeRecommendStoreTableViewCell.identifier
        )
        
        tableView.register(
            UITableViewCell.self,
            forCellReuseIdentifier: "cell"
        )
        
        tableView.delegate = self
        tableView.dataSource = self
        tableView.backgroundColor = .black
        
        tableView.showsVerticalScrollIndicator = false
        tableView.separatorStyle = .none
        tableView.contentInsetAdjustmentBehavior = .never
        
        self.tableView = tableView
        
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        guard let cell = tableView.dequeueReusableCell(withIdentifier: HomePopularTableViewCell.identifier, for: indexPath) as? HomePopularTableViewCell else { return tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)}
        cell.selectionStyle = .none
        return cell
    }
}

class TableViewCell: UITableViewCell, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
    
    static let identifier = "HomeRecommendStoreTableViewCell"
    
    private var collectionView: UICollectionView!
    
    
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        
        contentView.backgroundColor = .black
        setUpCollectionView()
    }
    
    required init?(coder: NSCoder) {
        fatalError()
    }
    
    func setUpCollectionView() {
        let layout = UICollectionViewFlowLayout()
        
        let collectionView = UICollectionView(
            frame: .zero,
            collectionViewLayout: layout
        )
        
        layout.scrollDirection = .horizontal
        collectionView.register(
            HomeRecommendStoreCollectionViewCell.self,
            forCellWithReuseIdentifier: HomeRecommendStoreCollectionViewCell.identifier
        )
        collectionView.register(
            UICollectionViewCell.self,
            forCellWithReuseIdentifier: "cell"
        )
        
        collectionView.clipsToBounds = false
        collectionView.backgroundColor = .black
        collectionView.showsHorizontalScrollIndicator = false
        
        collectionView.delegate = self
        collectionView.dataSource = self
        
        contentView.addSubview(collectionView)
        
        collectionView.snp.makeConstraints { make in
            make.top.equalToSuperview().offset(40)
            make.leading.equalToSuperview().offset(20)
            make.trailing.equalToSuperview()
            make.bottom.equalToSuperview().inset(80)
        }
        
        self.collectionView = collectionView
    }
    
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 5
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        
        guard let cell = collectionView.dequeueReusableCell(
            withReuseIdentifier: HomeRecommendStoreCollectionViewCell.identifier, for: indexPath
        ) as? HomeRecommendStoreCollectionViewCell else {
            return collectionView.dequeueReusableCell(
                withReuseIdentifier: "cell", for: indexPath
            )
        }
        return cell
    }
}

class CollectionViewCell: UICollectionViewCell {
    static let identifier = "HomeRecommendStoreCollectionViewCell"
    
    private lazy var listButton: UIButton = {
        let button = UIButton()
        return button
    }()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        setUp()
    }
    
    func setUp() {
        listButton.addTarget(self, action: #selector(onTap), for: .touchUpInside)
    }
    
    @objc func onTap() {
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

【问题讨论】:

  • 同样的问题已经被问过很多次了。使用闭包。
  • 我找不到任何东西。这就是我写这个问题的原因。请给我一个链接。如果你不介意。我无法理解使用闭包。在哪里?
  • 在单元格中使用类似 didSelectItem 的协议并设置为主 vc

标签: ios swift delegates collectionview


【解决方案1】:

首先你必须在 tableViewCell 中创建一个属性:

weak var parent:ViewController?

然后在 viewController 中你必须使用单元格作为 tableView 的行:

cell.parent = self

然后在 collectionViewCell 中创建相同的属性:

weak var parent:ViewController?

并使用collectionView func cell作为项目:

cell.parent = parent

并在按钮 func 中使用该父级:

 @objc func onTap() {
    let destinationVC = NextViewController()
    parent?.navigationController.pushViewController(destinationVC,animated:true)
}

【讨论】:

  • 使用weak传递控制器。 weak var parent: ViewController? 否则它会捕捉到强大的自我和不释放内存的机会。
  • 感谢您的意见,我将编辑我的答案:)
【解决方案2】:

由于委托在 collectionView 中,您可以在 TableView 单元格中获得回调,然后使用另一个委托,您可以在 ViewController 中获得回调。

或者您也可以使用通知来获取回调。

也可以使用闭包。

【讨论】: