47

In my UITableViewController I have a custom cell which contains a switcher which is the following:

import Foundation
import UIKit

class SwitchCell: UITableViewCell {
  @IBOutlet weak var label : UILabel!
  @IBOutlet weak var switchEmail : UISwitch!

  func setEditable(canEdit:Bool) {
      if (canEdit) {
        self.switchEmail.enabled = true
        self.label.highlighted = false
      }
      else {
          self.switchEmail.enabled = false
          self.label.highlighted = true
      }
  }

  func configureCellWithSwitch(labelText:String, switchValue:Bool, enabled:Bool) {

    var labelFrame:CGRect = self.label.frame
    labelFrame.size.height = Settings.labelHeight
    self.label.frame = labelFrame

    self.label.text = labelText

    if (switchValue) {
        self.switchEmail.setOn(true, animated: true)
    }
    else {
        self.switchEmail.setOn(false, animated: true)
    }

    self.setEditable(enabled)

  }
}

I would like to know how to implement a listener/delegate to the switcher in order to get its value from the UITableViewController. I was able to write delegate/listeners for a cell with UITextField and UITextView implementing the methods

func controller(controller: UITableViewCell, textViewDidEndEditing: String, atIndex: Int)

and

func controller(controller: UITableViewCell, textFieldDidEndEditingWithText: String, atIndex: Int)

but I don't know what I should implement the switcher.

Kiran Sarvaiya
  • 1,318
  • 1
  • 13
  • 37
SagittariusA
  • 5,289
  • 15
  • 73
  • 127

7 Answers7

122

UISwitch has no delegate protocol. You can listen to the status as follows:

ObjC:

// somewhere in your setup:
[self.mySwitch addTarget:self action:@selector(switchChanged:) forControlEvents:UIControlEventValueChanged];


- (void)switchChanged:(UISwitch *)sender {
   // Do something
   BOOL value = sender.on;
}

Swift:

mySwitch.addTarget(self, action: "switchChanged:", forControlEvents: UIControlEvents.ValueChanged)

func switchChanged(mySwitch: UISwitch) {
   let value = mySwitch.on
   // Do something
}

Swift3 :

mySwitch.addTarget(self, action: #selector(switchChanged), for: UIControlEvents.valueChanged)

func switchChanged(mySwitch: UISwitch) {
    let value = mySwitch.isOn
    // Do something
}

Swift4:

mySwitch.addTarget(self, action: #selector(switchChanged), for: UIControl.Event.valueChanged)

@objc func switchChanged(mySwitch: UISwitch) {
    let value = mySwitch.isOn
    // Do something
}
Quinn
  • 7,072
  • 7
  • 39
  • 61
dibi
  • 3,257
  • 4
  • 24
  • 31
  • Ok, this is what I have just written inside the class cell in the init( ). I would like to know how can I retrieve the switch value from my table view controller...which method should I implement there? – SagittariusA Sep 15 '15 at 13:15
  • 1
    @LoryLory see my update: the value of `UISwitch` is available via `.on` – dibi Sep 15 '15 at 13:20
  • Ah ok, that method is supposed to be inside the TableView right? I thought it was inside the custom class cell... that's why I didn't know how to get the value from the table view controller – SagittariusA Sep 15 '15 at 13:23
  • and do not forget, do **addTarget** in init procedure, but put func **switchChanged** outside it – djdance Jan 09 '16 at 16:22
12

In Swift4.0

mySwitch.addTarget(self, action: #selector(valueChange), for:UIControlEvents.valueChanged)

 @objc func valueChange(mySwitch: UISwitch) {
        let value = mySwitch.isOn
        // Do something
        print("switch value changed \(value)")
    }
Mujahid Latif
  • 596
  • 7
  • 18
11

Another (Swift 3 or 4) method is to use didSet observer and drastically reduce code, like so-

In the class declaration declare a variable like below:

var switchFlag: Bool = false {
        didSet{               //This will fire everytime the value for switchFlag is set
            print(switchFlag) //do something with the switchFlag variable
        }
    }

Then you can have an IBAction on the UISwitch like so

@IBAction func switchChanged(_ sender: Any) {
        if self.mySwitch.isOn{
            switchFlag = true
        }else{
            switchFlag = false
        }
    }
Anjan Biswas
  • 7,746
  • 5
  • 47
  • 77
10

Swift 3:

Using Storyboard Autolayout:

Add Reference:

@IBOutlet weak var sampleSwitch: UISwitch!

Associate method:

@IBAction func sampleSwitchValueChanged(_ sender: Any) {

    if sampleSwitch.isOn {
        print("ON")  
    }
    else {
        print ("OFF")
    }
}

Programatic way:

Adding Target:

sampleSwitch.addTarget(self, action: #selector(ViewController.sampleSwitchValueChanged(sender:)), for: UIControlEvents.valueChanged)

The method associated with the switch:

   func sampleSwitchValueChanged(sender: UISwitch!)
    {
        if sender.isOn {

            print("switch on")

        } else {

        }
    }
Alvin George
  • 14,148
  • 92
  • 64
4

In Swift 5

switchDemo.addTarget(self, action: #selector(didTapAdvertise), for:UIControl.Event.valueChanged)

@objc func didTapAdvertise(mySwitch: UISwitch) {
        let value = mySwitch.isOn
        // Do something
        print("switch value changed \(value)")
    }
Khawar Islam
  • 2,556
  • 2
  • 34
  • 56
3

Swift 3:

@IBOutlet weak var mySwitch: UISwitch!  

mySwitch.addTarget(self, action: #selector(MyClass.switchChanged(_:)), for: UIControlEvents.valueChanged)

func switchChanged(_ mySwitch: UISwitch) {
    if mySwitch.isOn {
        // handle on
    } else {
        // handle off
    }
}
David Seek
  • 16,783
  • 19
  • 105
  • 136
2

I have the solution in objective-c, it is the method that I use regularly:

-The Action of the switch must be in tableviewcontroller and not on the cell

-When You tap on the switch inside the action can do this to find the correct cell, then you can easily find the index or any other value that you need ...

- (IBAction)switchValueChanged:(UISwitch *)sender
{
    YourCellClass *cell = (YourCellClass *)[sender findSuperViewWithClass:[YourCellClass class]];
        etc....
    }

the method findSuperviewWithClass is a category on UIView

- (UIView *)findSuperViewWithClass:(Class)superViewClass
{
    UIView *superView = self.superview;
    UIView *foundSuperView = nil;

    while (nil != superView && nil == foundSuperView)
    {
        if ([superView isKindOfClass:superViewClass])
        {
            foundSuperView = superView;
        } else
        {
            superView = superView.superview;
        }
    }
    return foundSuperView;
}
matti157
  • 1,288
  • 2
  • 13
  • 26