Renan Geraldo
Renan Geraldo

Reputation: 655

Protocol and Delegation in Swift

I'm trying to make a protocol and a delegate in Swift but i'm having some issues. I want to have a switch button in the cells of a Table View. Here is my protocol:

import Foundation
import UIKit

protocol CellProtocol {
    func onSwitchToogle (sender : AnyObject , onCell : UITableViewCell)
}

Here is my cell class:

import UIKit

class Cell: UITableViewCell {

    @IBOutlet weak var label: UILabel!
    @IBOutlet weak var flag: UISwitch!
    var cellDelegate:CellProtocol!

    @IBAction func Toogle(sender: AnyObject) {
        if((cellDelegate?.onSwitchToogle(sender, onCell: self)) != nil){

        }
    }
}

And here is my ViewController:

import UIKit

class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, CellProtocol {    
    func onSwitchToogle(sender: AnyObject, onCell: UITableViewCell) {

    }

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

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
         let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! Cell 
        cell.label.text = "sadsad"
        return cell
    }
}

The problem is: it never enters in the if condition in the IBAction of my switch and it never enters in the method on the ViewController.

Upvotes: 2

Views: 141

Answers (2)

Rob
Rob

Reputation: 437432

A couple of things:

  1. You want to make sure that you specify the delegate in cellForRowAtIndexPath:

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! Cell 
        cell.cellDelegate = self
        cell.label.text = "sadsad"
        return cell
    }
    
  2. Make sure you don't have a strong reference cycle by making the cellDelegate property weak:

    weak var cellDelegate: CellProtocol!
    
  3. To allow you to have weak references to the protocol type, you must make the protocol a class protocol:

    protocol CellProtocol : class {
        func onSwitchToggle (sender : AnyObject, onCell : UITableViewCell)
    }
    
  4. You obviously just want to call onSwitchToggle if the delegate is set (using optional chaining):

    @IBAction func toggle(sender: AnyObject) {
        cellDelegate?.onSwitchToggle(sender, onCell: self)
    }
    

    No test is required to make sure the delegate implemented the method, because if the view controller conforms to the protocol, it must implement that method.

Please forgive me, but I changed a method names (toggle vs toogle, start methods names with lowercase letters, etc.), but hopefully this illustrates the key points.

Upvotes: 1

Greg
Greg

Reputation: 25459

In cellForRowAtIndexPath set up the delegate to self:

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

         let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! Cell

        cell.label.text = "sadsad"
        cell.cellDelegate = self

        return cell

    }

Upvotes: 0

Related Questions