You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

UITextField.rightView中的UIControl无法响应controlEvents事件求助

问题原因与解决方案

问题原因

  1. UITextField的rightView交互限制:当把普通UIView作为UITextField的rightView时,系统会默认限制其内部子视图的事件传递,导致子UIControl无法接收到触摸事件;而UIButton作为UIControl子类,直接作为rightView时会被UITextField特殊处理交互逻辑,因此能正常响应。
  2. 重复修改视图层次:你在viewDidLayoutSubviews中每次都会创建新的searchView并重新设置为rightView,频繁变更视图层次会干扰触摸事件的正常传递路径。

解决方案

  • 开启容器视图交互:显式设置作为rightView的UIView的isUserInteractionEnabled = true,确保触摸事件能传递到子UIControl。
  • 固定视图创建逻辑:将容器视图创建、添加UIControl、设置rightView的代码移到viewDidLoad中,只执行一次,保证视图层次稳定。
  • 可选:显式开启UIControl交互:虽然UIControl默认已开启交互,显式设置可避免系统意外修改。

修改后的代码

import UIKit
class DemoControl: UIControl { }
class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        view.addSubview(searchBar)
        
        // 视图创建逻辑移到viewDidLoad,仅执行一次
        let searchView = UIView(frame: CGRect(x: 0, y: 0, width: demoControl.frame.width, height: demoControl.frame.height))
        searchView.isUserInteractionEnabled = true
        searchView.addSubview(demoControl)
        searchBar.searchTextField.rightViewMode = .always
        searchBar.searchTextField.rightView = searchView
    }

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        // 仅处理布局自适应,不再重复设置rightView
    }

    private lazy var searchBar: UISearchBar = {
        let view = UISearchBar(frame: CGRect(x: 0, y: 100, width: UIScreen.main.bounds.width - 24, height: 36))
        return view
    }()

    private lazy var demoControl: DemoControl = {
        let control = DemoControl(frame: CGRect(x: 0, y: 0, width: 52, height: 24))
        control.layer.cornerRadius = 12
        control.backgroundColor = .red
        control.isUserInteractionEnabled = true
        control.addTarget(self, action: #selector(controlAction), for: .touchUpInside)
        return control
    }()

    private lazy var demoButton: UIButton = {
        let control = UIButton(frame: CGRect(x: 0, y: 0, width: 52, height: 24))
        control.layer.cornerRadius = 12
        control.backgroundColor = .red
        control.addTarget(self, action: #selector(controlAction), for: .touchUpInside)
        return control
    }()

    @objc private func controlAction() {
        print("Click!!!")
    }
}

内容的提问来源于stack exchange,提问作者Allen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 11:25:18