Swift中多层嵌套UIButton点击通过代理链传至ViewController可行吗?
Absolutely! Your plan to create a delegate chain (UICollectionViewCell → UITableViewCell → ViewController) is totally valid and a common, reliable pattern for handling nested UI interactions in iOS. While it adds an extra layer of delegation, it keeps each component’s responsibilities focused and avoids tight coupling between unrelated classes—so it’s a solid solution.
Step-by-Step Implementation Guide
Let’s break down how to make this work smoothly:
1. Add a Delegate Protocol to Your AnswerOptionCell
First, define a protocol in your collection view cell to notify its parent table view cell when the button is tapped:
protocol AnswerOptionCellDelegate: AnyObject { func answerOptionCellButtonTapped(_ cell: AnswerOptionCell) } class AnswerOptionCell: UICollectionViewCell { weak var delegate: AnswerOptionCellDelegate? // Button tap action @IBAction func optionButtonTapped(_ sender: UIButton) { delegate?.answerOptionCellButtonTapped(self) } }
2. Extend Your UITableViewCell to Act as the Collection Cell Delegate
Next, have your table view cell adopt the AnswerOptionCellDelegate protocol, and create a new protocol to pass the event up to the view controller:
protocol OptionTableViewCellDelegate: AnyObject { func optionTableViewCellDidSelectOption(_ cell: OptionTableViewCell, selectedOptionCell: AnswerOptionCell) } class OptionTableViewCell: UITableViewCell, UICollectionViewDataSource, UICollectionViewDelegate, AnswerOptionCellDelegate { weak var delegate: OptionTableViewCellDelegate? // Configure collection view cells func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "AnswerOptionCell", for: indexPath) as! AnswerOptionCell cell.delegate = self return cell } // Handle tap from collection cell func answerOptionCellButtonTapped(_ cell: AnswerOptionCell) { delegate?.optionTableViewCellDidSelectOption(self, selectedOptionCell: cell) } }
3. Connect the View Controller to the Table View Cell Delegate
Finally, have your view controller adopt the OptionTableViewCellDelegate protocol, set itself as the delegate when configuring table cells, and run your desired method:
class MainViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, OptionTableViewCellDelegate { func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "OptionTableViewCell", for: indexPath) as! OptionTableViewCell cell.delegate = self return cell } // Trigger your ViewController method here func optionTableViewCellDidSelectOption(_ cell: OptionTableViewCell, selectedOptionCell: AnswerOptionCell) { // Replace with your actual logic print("Button tapped in nested collection cell! Executing ViewController method...") yourViewControllerMethod() } func yourViewControllerMethod() { // Your core logic here } }
Alternatives to Consider
If you want to explore other patterns (though your original plan is perfectly fine), you could try:
- Closures: Pass a closure from the view controller down through the table cell to the collection cell. This avoids multiple delegate protocols but can get messy if you need to pass complex data.
- Notification Center: Broadcast a notification when the button is tapped, and have the view controller observe it. This decouples components but makes debugging harder since communication is implicit.
But don’t overcomplicate things—your delegate chain approach is straightforward, easy to maintain, and works great for nested UI setups like yours.
内容的提问来源于stack exchange,提问作者Littlebobbydroptables

