Search code examples
iosswiftuicollectionviewtableviewuisegmentedcontrol

Sending a signal to collection view within tableview cell from a segment outlet in another tableview cell


I have a segment outlet in a tableview cell in a VC. There are two indexes: 1 and 2.

When I click on 2, I want to tell the collection view within another tableviewcell to reload another view.

And when I click back to 1, I want the same collection view to reload again and display the original content.

Here are my View Controller Functions:

class MyProfileTableViewController: UIViewController, UITableViewDelegate,   UITableViewDataSource,segment
 {

 //Variable selection to determine what is selected - 1 by default
 var viewSelected = "1"

 //Segment Function - viewSelected is used to tell VC what index it's on
  func segmentSelected(tag: Int, type: String) {
    if type == "1" {
        print("1")
        viewSelected = "1"
    } else if type == "2" {
        print("2")
        viewSelected = "2"
    }
 }


 //Cell For Row - tells tableviewcell to look at viewSelected
  func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
  let cell  = AboutTableView.dequeueReusableCell(withIdentifier: "ProfileSegmentTableViewCell", for: indexPath) as! ProfileSegmentTableViewCell
  cell.segmentCell = self
  return cell
  } else {
  let cell  = AboutTableView.dequeueReusableCell(withIdentifier: "1_2Cell", for: indexPath) as! 1_2Cell
  cell.viewSelected = viewSelected
  return cell
  }

Here is the Segment Control TableviewCell

 //protocol used to delegate
 protocol segment: UIViewController {
func segmentSelected(tag: Int, type: String)
}

class ProfileSegmentTableViewCell: UITableViewCell {

@IBOutlet weak var profileSegmentControl: UISegmentedControl!

var segmentCell: segment?


  @IBAction func segmentPressed(_ sender: Any) {
    profileSegmentControl.changeUnderlinePosition()
    
    let Index = self.profileSegmentControl.selectedSegmentIndex
    if Index == 0
    {
        segmentCell?.segmentSelected(tag: (sender as AnyObject).tag, type: "1")
        )
    } else {
        segmentCell?.segmentSelected(tag: (sender as AnyObject).tag, type: "2")
        
    }
}

CollectionView

 //variable by default
 var viewSelected = "1"

 //viewDidLoad
 override func awakeFromNib() {
    super.awakeFromNib()
    // Initialization code
    cView.delegate = self
    cView.dataSource = self
    get {
        self.cView.reloadData()
        self.cView.layoutIfNeeded()
    }
}

 func get(_ completionHandler: @escaping () -> Void)  {
  getCount.removeAll() 
  if viewSelected = "1" {
  print("1") } else {
  print("2)
  }
  completionHandler()
 }

Solution

  • Here's a very simple example of using a closure so your segmented-control cell can communicate with your table view controller.

    Your cell class might look like this:

    class ProfileSegmentTableViewCell: UITableViewCell {
        @IBOutlet var profileSegmentControl: UISegmentedControl!
        
        var callback: ((Int)->())?
        
        @IBAction func segmentPressed(_ sender: Any) {
            guard let segControl = sender as? UISegmentedControl else { return }
            // tell the controller that the selected segment changed
            callback?(segControl.selectedSegmentIndex)
        }
    }
    

    When the user changes the selected segment, the cell uses the callback closure to inform the controller that a segment was selected.

    Then, in your controller, you could have a var to track the currently selected segment index:

    // track selected segment index
    var currentIndex: Int = 0
    

    and your cellForRowAt code would look like this:

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        if indexPath.row == 0 {
            // first row - use cell with segemented control
            let cell = tableView.dequeueReusableCell(withIdentifier: "ProfileSegmentTableViewCell", for: indexPath) as! ProfileSegmentTableViewCell
            
            // set the segemented control's selected index
            cell.profileSegmentControl.selectedSegmentIndex = self.currentIndex
            
            // set the callback closure
            cell.callback = { [weak self] idx in
                guard let self = self else {
                    return
                }
                // update the segment index tracker
                self.currentIndex = idx
                // reload row containing collection view
                self.tableView.reloadRows(at: [IndexPath(row: 1, section: 0)], with: .automatic)
            }
            
            return cell
        } else if indexPath.row == 1 {
            // second row - use cell with collection view
            let cell = tableView.dequeueReusableCell(withIdentifier: "1_2Cell", for: indexPath) as! My_1_2Cell
            
            // tell the cell which segment index is selected
            cell.setData(currentIndex)
            
            return cell
        }
        
        // all other rows - use simple Basic cell
        let cell = tableView.dequeueReusableCell(withIdentifier: "PlainCell", for: indexPath) as! PlainCell
        cell.textLabel?.text = "Row \(indexPath.row)"
        return cell
    }
    

    Here is a complete example you can run and examine: https://github.com/DonMag/ClosureExample