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

iOS开发中addAction与addTarget的区别及按钮事件实现选型

UIControl 点击事件两种实现方式的核心差异

你提到的addTarget是UIKit从诞生起就沿用的经典Target-Action机制,addAction是iOS 14新增的基于UIAction的闭包式实现,二者核心区别主要在几个维度:

  • 运行时依赖差异
    传统addTarget完全基于Objective-C运行时的消息转发实现,必须给响应方法加@objc标记,通过#selector动态查找方法地址完成调用。编译期完全不会校验方法是否存在,一旦方法名拼错、权限不匹配,就会在运行时直接崩溃。
    系统原生的addAction基于Block闭包实现,完全不依赖Objective-C运行时,Swift原生代码可直接使用,所有调用逻辑在编译期就能完成校验,不会出现selector相关的运行时崩溃。
  • 内存引用逻辑差异
    addTarget模式下,控件对绑定的target是弱引用关系,不存在互相持有导致的循环引用问题,哪怕开发者忘记写弱引用,也不会因为绑定逻辑造成内存泄漏。
    addAction模式下,控件会强持有绑定的UIAction对象,UIAction又会强持有内部的闭包,如果闭包没有用[weak self]捕获持有控件的控制器/视图,就会形成「控制器->按钮->UIAction->闭包->控制器」的循环引用链,必须手动处理弱引用才能规避泄漏。
  • 功能灵活度差异
    传统addTarget只能简单绑定事件响应,想要精准移除绑定的响应,必须准确记录当初绑定的target、action、事件类型,参数稍有偏差就会出现漏移除、错移除的问题;如果给同一个控件重复绑定同target、同action、同事件的响应,后面的绑定会被直接去重覆盖,没法同时保留多个独立的响应逻辑。
    addAction支持同一个控件、同一个事件类型绑定多个独立的UIAction,每个action都可以带独立标识符,移除时可以通过标识符精准定位,不会出现误删问题。配合UIAction自带的属性,还可以直接联动按钮的选中状态、上下文菜单等能力,不需要额外写属性绑定逻辑。
  • 版本兼容差异
    addTarget从iOS 2.0开始就全版本支持,没有兼容门槛;原生addAction接口是iOS 14才正式推出的,如果要兼容更低版本,就需要像你写的那样,自己封装一层桥接逻辑,在低版本用addTarget做内部实现,对外暴露闭包接口。
日常开发的选型建议
  • 如果项目最低兼容版本在iOS 14及以上,优先直接使用原生addAction实现按钮点击:不需要写零散的@objc响应方法,点击逻辑可以直接和控件绑定写在同一个位置,代码内聚性更高,后续维护时不需要在类里到处翻找对应的响应方法,也能避免selector拼写错误的运行时风险。
  • 如果项目需要兼容iOS 14以下的版本,推荐用你写的那套统一闭包接口:内部在高版本走原生addAction,低版本走addTarget桥接,对外统一暴露闭包调用能力,既可以兼容全版本,又能统一团队的编码风格,避免一会用Target-Action、一会用手势的混乱写法。
  • 传统addTarget依然有适用场景:比如和历史悠久的Objective-C混编老项目,已经有成熟的Target-Action体系,不需要强行重构换用新接口;另外如果需要批量管控所有控件的事件响应(比如页面消失时统一移除所有事件绑定,避免页面销毁后收到野指针回调),addTarget提供的批量移除接口会比逐个找UIAction更方便。
  • 补充说明:不推荐用UITapGestureRecognizer实现普通按钮的点击事件。手势识别本身是为非UIControl的视图设计的,会拦截按钮原生的高亮、长按、事件传递逻辑,容易出现交互异常,只有给普通UIView加点击场景才推荐使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.24 18:45:08