Swift中Selector传递基础类型参数 无需自定义UIButton的解决方案问询
问题原因
#selector仅表示方法的签名指针,本身不支持绑定自定义参数,你在#selector中直接传入参数的写法不符合iOS的target-action机制规则,因此触发编译报错。
方案1:Tag + 映射字典
- 实现逻辑:给每个按钮分配唯一tag,在VC中维护tag和对应参数的映射关系,点击时通过按钮tag取出对应参数
- 代码示例:
// 1. 声明VC属性维护映射关系 private var buttonURLMap: [Int: String] = [:] // 2. 遍历创建按钮时赋值 let targetURL = "当前按钮对应的字符串" let button = UIButton() // tag加偏移量避免和系统其他视图tag冲突 button.tag = 1000 + index button.addTarget(self, action: #selector(didTapOnButton(_:)), for: .touchUpInside) buttonURLMap[button.tag] = targetURL // 3. 点击方法实现 @objc private func didTapOnButton(_ sender: UIButton) { guard let url = buttonURLMap[sender.tag] else { return } // 后续处理逻辑 }
方案2:Runtime关联对象
- 实现逻辑:通过Runtime的关联对象能力,给系统UIButton动态添加自定义属性存储参数,点击时直接从按钮实例取参数
- 代码示例:
// 1. 导入Runtime头文件 import ObjectiveC.runtime // 2. 给UIButton加扩展添加自定义属性 extension UIButton { private struct AssociatedKeys { static var customBindURL: UInt8 = 0 } var customBindURL: String? { get { objc_getAssociatedObject(self, &AssociatedKeys.customBindURL) as? String } set { objc_setAssociatedObject(self, &AssociatedKeys.customBindURL, newValue, .OBJC_ASSOCIATION_COPY_NONATOMIC) } } } // 3. 创建按钮时赋值 let targetURL = "当前按钮对应的字符串" let button = UIButton() button.customBindURL = targetURL button.addTarget(self, action: #selector(didTapOnButton(_:)), for: .touchUpInside) // 4. 点击方法实现 @objc private func didTapOnButton(_ sender: UIButton) { guard let url = sender.customBindURL else { return } // 后续处理逻辑 }
方案3:闭包回调封装
- 实现逻辑:通过关联对象给UIButton封装点击闭包,创建按钮时直接绑定当前上下文的参数,无需声明@objc方法
- 代码示例:
import ObjectiveC.runtime extension UIButton { private struct AssociatedKeys { static var tapAction: UInt8 = 0 } typealias ButtonTapAction = () -> Void var tapAction: ButtonTapAction? { get { objc_getAssociatedObject(self, &AssociatedKeys.tapAction) as? ButtonTapAction } set { objc_setAssociatedObject(self, &AssociatedKeys.tapAction, newValue, .OBJC_ASSOCIATION_COPY_NONATOMIC) addTarget(self, action: #selector(internalTriggerTap), for: .touchUpInside) } } @objc private func internalTriggerTap() { tapAction?() } } // 创建按钮时直接绑定逻辑 let targetURL = "当前按钮对应的字符串" let button = UIButton() button.tapAction = { [weak self] in // 直接使用当前上下文的参数,无需额外映射 self?.handleButtonTap(url: targetURL) } // 普通处理方法,无需@objc修饰 private func handleButtonTap(url: String) { // 后续处理逻辑 }
内容的提问来源于stack exchange,提问作者PK-V
相关产品推荐
相关产品推荐

