如何将闭包作为动作传递给添加到 UIView 的点击手势?
How to pass a closure as action to tap gesture added to a UIView?
我想要一个 UIView 上的点击功能,但我不知道如何在函数的第一张图片中传入那个闭包:
首先:我强烈建议在您的问题中添加代码片段而不是屏幕截图。
您需要为 UITapGestureRecognizer
中的操作参数传递 Selector
而不是 () -> ()
闭包:
extension UIView {
func onClick(target: Any, _ selector: Selector) {
isUserInteractionEnabled = true
let tap = UITapGestureRecognizer(target: target, action: selector)
addGestureRecognizer(tap)
}
}
此外,请记住,此时您必须为 tap
实例设置适当的 target
,这意味着它 而不是 self
在 UIView
扩展中(在您的代码中实现);相反,您必须将其作为参数传递给 onClick
方法。
用法:
在你的ViewController中:
likesImg.onClick(target: self, #selector(likesImgClicked))
@objc private func likesImgClicked() {
print(#function)
}
当说 likesImg.onClick(target: self
时:这里的 self
表示 ViewController 本身,而不是 UIView
扩展,这是正确的目标,因为 likesImgClicked
在ViewController 但不在 UIView
扩展中。
更新:
如果你坚持传递闭包的方法,你可以按照这个解决方案:
将您的 UIView 扩展实现为:
extension UIView {
private struct OnClickHolder {
static var _closure:()->() = {}
}
private var onClickClosure: () -> () {
get { return OnClickHolder._closure }
set { OnClickHolder._closure = newValue }
}
func onClick(target: Any, _ selector: Selector) {
isUserInteractionEnabled = true
let tap = UITapGestureRecognizer(target: self, action: selector)
addGestureRecognizer(tap)
}
func onClick(closure: @escaping ()->()) {
self.onClickClosure = closure
isUserInteractionEnabled = true
let tap = UITapGestureRecognizer(target: self, action: #selector(onClickAction))
addGestureRecognizer(tap)
}
@objc private func onClickAction() {
onClickClosure()
}
}
用法:
在你的ViewController中:
likesImg.onClick {
print("Hello!!")
}
重要提示:
感谢 @Josh Caswell 的以下说明:
Note that the private struct gets you one storage location for the
entire program. If you try to set a handler on more than one view,
the second will overwrite the first.
我刚刚根据一些答案重新设计了 swift 点击侦听器 android 样式。使用起来非常简单:
yourView.setClickListener {
// do some actions here!
}
将此添加到您的扩展文件中:
final class ClickListener: UITapGestureRecognizer {
private var action: () -> Void
init(_ action: @escaping () -> Void) {
self.action = action
super.init(target: nil, action: nil)
self.addTarget(self, action: #selector(execute))
}
@objc private func execute() {
action()
}
}
extension UIView {
func setClickListener(_ action: @escaping () -> Void) {
self.isUserInteractionEnabled = true
let click = ClickListener(action)
self.addGestureRecognizer(click)
}
}
我正在使用 Xcode 11.7 和 Swift 5.2
我创建了一个通用的按钮操作。请参考以下代码
import UIKit
func customBarButton(_ target: Any, selector: Selector, controlEvent: UIControl.Event, buttonImage: String) -> UIBarButtonItem{
let customButton = UIButton(type: .custom)
customButton.setImage(UIImage(named: buttonImage), for: .normal)
customButton.frame = CGRect(x: 0, y: 0, width: 24, height: 24)
customButton.addTarget(target, action: selector, for: controlEvent)
let filterItem = UIBarButtonItem(customView: customButton)
return filterItem
}
我在 viewcontroller 文件中使用了上述代码。
在 viewdidload 中初始化。
let searchItem = customBarButton(self, selector: #selector(didTapSearchButton(_:)), controlEvent: .touchUpInside, buttonImage: "search")
navigationItem.rightBarButtonItems = [searchItem]
触摸按钮时调用的函数:
@objc func didTapSearchButton(_ sender: Any){
//enter code here
}
我想要一个 UIView 上的点击功能,但我不知道如何在函数的第一张图片中传入那个闭包:
首先:我强烈建议在您的问题中添加代码片段而不是屏幕截图。
您需要为 UITapGestureRecognizer
中的操作参数传递 Selector
而不是 () -> ()
闭包:
extension UIView {
func onClick(target: Any, _ selector: Selector) {
isUserInteractionEnabled = true
let tap = UITapGestureRecognizer(target: target, action: selector)
addGestureRecognizer(tap)
}
}
此外,请记住,此时您必须为 tap
实例设置适当的 target
,这意味着它 而不是 self
在 UIView
扩展中(在您的代码中实现);相反,您必须将其作为参数传递给 onClick
方法。
用法:
在你的ViewController中:
likesImg.onClick(target: self, #selector(likesImgClicked))
@objc private func likesImgClicked() {
print(#function)
}
当说 likesImg.onClick(target: self
时:这里的 self
表示 ViewController 本身,而不是 UIView
扩展,这是正确的目标,因为 likesImgClicked
在ViewController 但不在 UIView
扩展中。
更新:
如果你坚持传递闭包的方法,你可以按照这个解决方案:
将您的 UIView 扩展实现为:
extension UIView {
private struct OnClickHolder {
static var _closure:()->() = {}
}
private var onClickClosure: () -> () {
get { return OnClickHolder._closure }
set { OnClickHolder._closure = newValue }
}
func onClick(target: Any, _ selector: Selector) {
isUserInteractionEnabled = true
let tap = UITapGestureRecognizer(target: self, action: selector)
addGestureRecognizer(tap)
}
func onClick(closure: @escaping ()->()) {
self.onClickClosure = closure
isUserInteractionEnabled = true
let tap = UITapGestureRecognizer(target: self, action: #selector(onClickAction))
addGestureRecognizer(tap)
}
@objc private func onClickAction() {
onClickClosure()
}
}
用法:
在你的ViewController中:
likesImg.onClick {
print("Hello!!")
}
重要提示:
感谢 @Josh Caswell 的以下说明:
Note that the private struct gets you one storage location for the entire program. If you try to set a handler on more than one view, the second will overwrite the first.
我刚刚根据一些答案重新设计了 swift 点击侦听器 android 样式。使用起来非常简单:
yourView.setClickListener {
// do some actions here!
}
将此添加到您的扩展文件中:
final class ClickListener: UITapGestureRecognizer {
private var action: () -> Void
init(_ action: @escaping () -> Void) {
self.action = action
super.init(target: nil, action: nil)
self.addTarget(self, action: #selector(execute))
}
@objc private func execute() {
action()
}
}
extension UIView {
func setClickListener(_ action: @escaping () -> Void) {
self.isUserInteractionEnabled = true
let click = ClickListener(action)
self.addGestureRecognizer(click)
}
}
我正在使用 Xcode 11.7 和 Swift 5.2
我创建了一个通用的按钮操作。请参考以下代码
import UIKit
func customBarButton(_ target: Any, selector: Selector, controlEvent: UIControl.Event, buttonImage: String) -> UIBarButtonItem{
let customButton = UIButton(type: .custom)
customButton.setImage(UIImage(named: buttonImage), for: .normal)
customButton.frame = CGRect(x: 0, y: 0, width: 24, height: 24)
customButton.addTarget(target, action: selector, for: controlEvent)
let filterItem = UIBarButtonItem(customView: customButton)
return filterItem
}
我在 viewcontroller 文件中使用了上述代码。
在 viewdidload 中初始化。
let searchItem = customBarButton(self, selector: #selector(didTapSearchButton(_:)), controlEvent: .touchUpInside, buttonImage: "search")
navigationItem.rightBarButtonItems = [searchItem]
触摸按钮时调用的函数:
@objc func didTapSearchButton(_ sender: Any){
//enter code here
}