使用委托和协议的集合视图单元格操作

Posted

技术标签:

【中文标题】使用委托和协议的集合视图单元格操作【英文标题】:Collection View Cell Action using Delegates and Protocols 【发布时间】:2019-08-23 13:24:41 【问题描述】:

我创建了一个包含 UITableView 的 View Controller,每个 UITableViewCell 都包含一个 UICollectionView。

我进行了 2 次 API 调用,每个 collectionView 都会显示每个 API 调用的前 5 个结果。

另外,我在每个 TableView 标题的右上角添加了一个按钮,标题为“全部显示”。您可以在下图中看到屏幕。

这是我添加 tableView 标题按钮的方法:

func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? 
    let headerView = UIView(frame: CGRect(x: 0, y: 0, width: tableView.frame.width, height: 100))

    let showHideButton: UIButton = UIButton(frame: CGRect(x:headerView.frame.size.width - 80, y:0, width:75, height:35))
    showHideButton.setTitle("Show All", for: .normal)
    showHideButton.titleLabel?.font = UIFont.boldSystemFont(ofSize: 18)
    showHideButton.setTitleColor(#colorLiteral(red: 0.9607843137, green: 0.007843137255, blue: 0.03137254902, alpha: 1), for: .normal)
    //showHideButton.addTarget(self, action: #selector(btnShowHideTapped), for: .touchUpInside)

    headerView.addSubview(showHideButton)

    return headerView

当我点击 tableView 标题上的“显示全部”按钮时,我想跳转到另一个视图控制器(“showAllViewController”)并表示我的对象的所有结果,当我点击 CollectionViewCell 的图像时,我想跳转到另一个视图控制器(“detailsViewController”)。我如何使用委托和协议来做到这一点?

这是我的屏幕的示例图像:

编辑:我按照这个问题 (navigate on click of collectionview cell inside tableview) 中的以下步骤操作,但我不知道我需要在“cellTapped()”函数上写什么:

ViewController.swift :

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! CategoryRow
        cell.delegate = self
        return cell
    

MyCell.swift :

protocol CategoryRowDelegate:class 
func cellTapped()

CategoryRow.swift :

class CategoryRow : UITableViewCell 
     weak var delegate:CategoryRowDelegate?
    @IBOutlet weak var collectionView: UICollectionView!


 func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) 
if delegate!= nil 
delegate?.cellTapped()


在 ViewController 中添加委托函数

func cellTapped()
//code for navigation
//I don't know what to write

谁能帮帮我?

【问题讨论】:

我认为您不需要委托来执行此操作,您可以直接在单元格点击或按钮操作事件上显示视图控制器 使用 //showHideButton.addTarget(self, action:#selector(btnShowHideTapped),for: .touchUpInside)。然后在 btnShowHideTapped() 中使用 segue(或许多方法中的另一种)转到下一个视图控制器。然后在 prepareForSegue 中,您可以根据需要将一些信息发送到下一个视图控制器。 这行代码是从网上复制粘贴的。我需要在选择器属性中添加什么? 您将处理水龙头的函数的名称放在选择器部分。下面是一个例子:addTarget(self, action: #selector(NameOfFunctionWhichHandles), for: UIControl.Event.touchUpInside) 什么应该包含处理水龙头的功能? 【参考方案1】:

首先我会建议你在创建按钮时插入一个标签,这样你就知道用户点击了集合中的哪个按钮,然后添加:

showHideButton.tag = section // assign the section number to the tag of the button

然后,正如您已经在代码中编写的那样,您为按钮单击分配一个动作:

showHideButton.addTarget(self, action: #selector(self.btnShowHideTapped(sender:)), for: .touchUpInside)

所以你最终会得到类似的东西:

showHideButton.setTitle("Show All", for: .normal)
showHideButton.titleLabel?.font = UIFont.boldSystemFont(ofSize: 18)
showHideButton.setTitleColor(#colorLiteral(red: 0.9607843137, green: 0.007843137255, blue: 0.03137254902, alpha: 1), for: .normal)
showHideButton.tag = section // section Number for Header
showHideButton.addTarget(self, action: #selector(self.btnShowHideTapped(sender:)), for: .touchUpInside) // Sender UIButton

在你的函数中你回调点击=>

@objc func btnShowHideTapped(sender: UIButton) 
   print(sender.tag)
   // Switch Action if is HeaderView 0 or HeaderView 1 etc...
   // self.present(YourViewController...) OR self.performSegue(withIdentifier: "detailsViewController", sender: nil)

我希望我一直在你身边。告诉我。

【讨论】:

谢谢!但我想用当前的集合视图数据呈现一个视图控制器。每次都不是同一个静态视图控制器。我想通过某种方式我需要覆盖准备函数。对吗? 你能告诉我当我点击单元格时如何跳转到另一个视图控制器吗?这对我现在更重要。谢谢! 我回答了你,只是制作或礼物或调用追随者......取决于你想如何移动到下一个视图控制器......看看我写给你的例子......跨度> 你也可以看这里:***.com/questions/24099533/… 或 developer.apple.com/documentation/uikit/uiviewcontroller/… 这一切都取决于你想如何呈现你的 viewController 好的,谢谢!这适用于“显示全部”按钮。当我点击 collectionView 单元格时会怎样?【参考方案2】:
1] In separate dataSource method - create protocol
    
    protocol myProductsDelegate: class 
        
        func cellTaped()
       
    
    class ProductsDataSource: NSObject, UICollectionViewDataSource 
    
        var delegate: myProductsDelegate?
        
    //    func collectionView(_ collectionView: UICollectionView, //numberOfItemsInSection section: Int) -> Int
     //   
    //        return 
    //    
        
        func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell 
            
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! ProductsCollectionViewCell
            
           
            return cell
            
    
 2] In separate delegate method -

class ProductsDelegate: NSObject, UICollectionViewDelegate 
    
    var delegate: myProductsDelegate?
    
        func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) 
            if delegate != nil 
                delegate?.cellTaped()
            
        
    
    3] Note: In viewDidload - 
    
            self.CollectionView.delegate = self.myDelegate
            self.CollectionView.dataSource = self.myDataSource
            self.myDelegate.delegate = self
    
    4] In your main view controller where collectionView is available - 

    var myDelegate: ProductsDelegate = ProductsDelegate()
    var myDataSource: ProductsDataSource = ProductsDataSource()
    
     extension MainViewController: ProductsDelegate 
    
        func cellTaped() 
    
            let vc = storyboard?.instantiateViewController(identifier: "SecondViewController") as? SecondViewController
            self.present(vc!, animated: true, completion: nil)
        
        

【讨论】:

以上是关于使用委托和协议的集合视图单元格操作的主要内容,如果未能解决你的问题,请参考以下文章

如何仅使用静态单元格创建集合视图? [复制]

使用自定义集合视图布局快速配置动态单元格高度

在实例化单元格之前调用 UICollectionView 委托方法?

使用协议从集合视图单元格中删除核心数据

UICollectionView 总是自动调整单元格大小。不使用委托返回的尺寸

预先创建 UICollectionView 单元格 - 布局问题