Swift/UISwitch: 如何实现一个委托/监听器

47

在我的UITableViewController中,我有一个包含开关的自定义单元格,它如下所示:

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)

  }
}
我想知道如何在UITableViewController中实现一个监听器/委托来获取其开关的值。我已经能够为带有UITextField和UITextView的单元格编写委托/监听器并实现了相应的方法。
func controller(controller: UITableViewCell, textViewDidEndEditing: String, atIndex: Int)

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

但是我不知道该如何实现切换器。

7个回答

122

UISwitch没有委托协议。您可以按以下方式监听其状态:

Objective-C:

// 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
}

好的,这是我刚在init()中编写的类单元格内容。我想知道如何从我的表视图控制器中检索开关值...我应该实现哪个方法? - SagittariusA
1
@LoryLory请看我的更新:UISwitch的值可以通过.on获得。 - dibi
啊,好的,那个方法应该在TableView里面对吧?我以为它在自定义的Cell类里面...所以我不知道如何从表视图控制器中获取值。 - SagittariusA
不要忘记,在初始化过程中添加 addTarget,但是将函数 switchChanged 放在外面。 - djdance

12

在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)")
    }

11

另一种(Swift 3或4)的方法是使用didSet观察器并极大地减少代码,像这样-

在类声明中声明一个如下所示的变量:

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

然后,您可以在UISwitch上有一个IBAction,如下所示

@IBAction func switchChanged(_ sender: Any) {
        if self.mySwitch.isOn{
            switchFlag = true
        }else{
            switchFlag = false
        }
    }

好主意!我不知道为什么以前没有人描述过使用@IBAction方法的简单解决方案。 - Klemen Tusar

10

Swift 3:

使用Storyboard Autolayout:

添加参考:

@IBOutlet weak var sampleSwitch: UISwitch!

关联方法:

@IBAction func sampleSwitchValueChanged(_ sender: Any) {

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

编程方式:

添加目标:

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

与开关相关联的方法:

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

            print("switch on")

        } else {

        }
    }

4
在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)")
    }

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
    }
}

2

我有一个用于objective-c的解决方案,这是我经常使用的方法:

-开关的操作必须在tableviewcontroller中进行,而不是在单元格上

-当您点击开关时,可以在操作中查找正确的单元格,然后轻松找到所需的索引或任何其他值...

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

方法findSuperviewWithClass是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;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接