键盘显示时UISwitch的Selector无法触发问题求助
问题分析与解决方案
核心原因
你遇到的问题根源在于UISwitch的事件绑定时机错误:在类属性的闭包初始化代码中,addTarget(self, action: ...)里的self是未完成初始化的实例。因为闭包执行时EndTimeCell的对象还没创建完成,导致target绑定失效。键盘未显示时事件传递路径可能存在特殊处理,让绑定偶然生效;但键盘弹出后系统事件处理逻辑更严格,失效问题就直接显现了。
修复方案
将UISwitch的target绑定逻辑移到init方法中,确保实例完全初始化后再绑定事件:
class EndTimeCell: UITableViewCell { var label: UILabel = { let lbl = UILabel() lbl.text = "End" lbl.font = UIFont.systemFont(ofSize: 17, weight: .semibold) lbl.textColor = UIColor.gray return lbl }() // 仅初始化UISwitch,不在此处绑定事件 var enable: UISwitch = { let en = UISwitch() return en }() var callback: (_ state: Bool) -> Void = {state in} @objc func onSwitchValueChanged(_ toggle: UISwitch) { print("CHANGED CHANGED CHANGED") label.textColor = toggle.isOn ? UIColor(named: "Secondary") : .gray callback(toggle.isOn) } func layoutView() { label.translatesAutoresizingMaskIntoConstraints = false enable.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ label.centerYAnchor.constraint(equalTo: contentView.safeAreaLayoutGuide.centerYAnchor), label.leftAnchor.constraint(equalTo: contentView.safeAreaLayoutGuide.leftAnchor, constant: Constants.padding + Constants.textFieldCornerRadius), enable.centerYAnchor.constraint(equalTo: contentView.safeAreaLayoutGuide.centerYAnchor), enable.rightAnchor.constraint(equalTo: contentView.safeAreaLayoutGuide.rightAnchor, constant: -Constants.padding), ]) } func setCallback(callback: @escaping (_ state: Bool) -> Void) { self.callback = callback } override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) contentView.addSubview(label) contentView.addSubview(enable) // 实例初始化完成后绑定事件 enable.addTarget(self, action: #selector(onSwitchValueChanged(_:)), for: .valueChanged) layoutView() } required init?(coder: NSCoder) { super.init(coder: coder) contentView.addSubview(label) contentView.addSubview(enable) // 实例初始化完成后绑定事件 enable.addTarget(self, action: #selector(onSwitchValueChanged(_:)), for: .valueChanged) layoutView() } override func layoutSubviews() { super.layoutSubviews() layoutView() } }
额外注意事项
- 禁止在类属性的闭包初始化中直接引用
self,除非使用lazy var延迟初始化(但此场景下移到init更稳妥) - 键盘弹出时,系统会优先处理键盘相关的响应链,无效的target会被直接忽略,这就是为什么键盘显示时selector完全不触发的原因
内容的提问来源于stack exchange,提问作者kasandell
相关产品推荐
相关产品推荐

