Ilk*_*aci 34 uibutton ios swift addtarget
我有一个通用控件类,需要根据视图控制器设置按钮的完成.由于setLeftButtonActionWithClosure函数需要将一个闭包作为参数,应该将其设置为解除操作的动作.如何在Swift中实现因为我们需要将函数名称作为String传递给action:parameter.
func setLeftButtonActionWithClosure(completion: () -> Void)
{
self.leftButton.addTarget(<#target: AnyObject?#>, action: <#Selector#>, forControlEvents: <#UIControlEvents#>)
}
Run Code Online (Sandbox Code Playgroud)
aep*_*yus 89
类似的解决方案已经列出,但可能更轻:
@objc class ClosureSleeve: NSObject {
let closure: ()->()
init (_ closure: @escaping ()->()) {
self.closure = closure
}
@objc func invoke () {
closure()
}
}
extension UIControl {
func addAction(for controlEvents: UIControl.Event = .touchUpInside, _ closure: @escaping ()->()) {
let sleeve = ClosureSleeve(closure)
addTarget(sleeve, action: #selector(ClosureSleeve.invoke), for: controlEvents)
objc_setAssociatedObject(self, "[\(arc4random())]", sleeve, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
button.addAction {
print("Hello, Closure!")
}
Run Code Online (Sandbox Code Playgroud)
或者如果避免保留循环:
button.addAction(for: .touchUpInside) {
print("Hello, Closure!")
}
Run Code Online (Sandbox Code Playgroud)
用户MH175提到如果他们使用控件上的"allTargets属性:静态Set_unnconditionalBridgeFromObjectiveC(_ :) - ",将会获得运行时异常.从NSObject扩展ClosureSleeve将解决此问题:
self.button.addAction(for: .touchUpInside) { [unowned self] in
self.doStuff()
}
Run Code Online (Sandbox Code Playgroud)
Arm*_*ide 29
注意:像@EthanHuang说的那样"如果你有两个以上的实例,这个解决方案就不起作用了.所有的操作都会被最后一个任务覆盖." 开发时请记住这一点,我会尽快发布另一种解决方案.
如果要将闭包作为目标添加到a UIButton,则必须UIButton使用向类添加函数extension
import UIKit
extension UIButton {
private func actionHandler(action:(() -> Void)? = nil) {
struct __ { static var action :(() -> Void)? }
if action != nil { __.action = action }
else { __.action?() }
}
@objc private func triggerActionHandler() {
self.actionHandler()
}
func actionHandler(controlEvents control :UIControl.Event, ForAction action:@escaping () -> Void) {
self.actionHandler(action: action)
self.addTarget(self, action: #selector(triggerActionHandler), for: control)
}
}
Run Code Online (Sandbox Code Playgroud)
和电话:
import UIKit
extension UIButton {
private func actionHandleBlock(action:(() -> Void)? = nil) {
struct __ {
static var action :(() -> Void)?
}
if action != nil {
__.action = action
} else {
__.action?()
}
}
@objc private func triggerActionHandleBlock() {
self.actionHandleBlock()
}
func actionHandle(controlEvents control :UIControlEvents, ForAction action:() -> Void) {
self.actionHandleBlock(action)
self.addTarget(self, action: "triggerActionHandleBlock", forControlEvents: control)
}
}
Run Code Online (Sandbox Code Playgroud)
Jac*_*llo 14
您可以通过继承UIButton来有效地实现此目的:
class ActionButton: UIButton {
var touchDown: ((button: UIButton) -> ())?
var touchExit: ((button: UIButton) -> ())?
var touchUp: ((button: UIButton) -> ())?
required init?(coder aDecoder: NSCoder) { fatalError("init(coder:)") }
override init(frame: CGRect) {
super.init(frame: frame)
setupButton()
}
func setupButton() {
//this is my most common setup, but you can customize to your liking
addTarget(self, action: #selector(touchDown(_:)), forControlEvents: [.TouchDown, .TouchDragEnter])
addTarget(self, action: #selector(touchExit(_:)), forControlEvents: [.TouchCancel, .TouchDragExit])
addTarget(self, action: #selector(touchUp(_:)), forControlEvents: [.TouchUpInside])
}
//actions
func touchDown(sender: UIButton) {
touchDown?(button: sender)
}
func touchExit(sender: UIButton) {
touchExit?(button: sender)
}
func touchUp(sender: UIButton) {
touchUp?(button: sender)
}
}
Run Code Online (Sandbox Code Playgroud)
使用:
let button = ActionButton(frame: buttonRect)
button.touchDown = { button in
print("Touch Down")
}
button.touchExit = { button in
print("Touch Exit")
}
button.touchUp = { button in
print("Touch Up")
}
Run Code Online (Sandbox Code Playgroud)
Hej*_*azi 10
现在,这在iOS 14上已成为可能。UIAction当您创建 时,您可以传递一个具有处理程序闭包的UIButton:
let action = UIAction(title: "") { action in
print("Button tapped!")
}
UIButton(type: .system, primaryAction: action)
Run Code Online (Sandbox Code Playgroud)
或者更短:
UIButton(type: .system, primaryAction: UIAction(title: "") { action in
print("Button tapped!")
})
Run Code Online (Sandbox Code Playgroud)
与已经列出的解决方案类似,但重量可能更轻,并且不依赖于随机性来生成唯一 ID:
class ClosureSleeve {
let closure: ()->()
init (_ closure: @escaping ()->()) {
self.closure = closure
}
@objc func invoke () {
closure()
}
}
extension UIControl {
func add (for controlEvents: UIControlEvents, _ closure: @escaping ()->()) {
let sleeve = ClosureSleeve(closure)
addTarget(sleeve, action: #selector(ClosureSleeve.invoke), for: controlEvents)
objc_setAssociatedObject(self, String(ObjectIdentifier(self).hashValue) + String(controlEvents.rawValue), sleeve,
objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
button.add(for: .touchUpInside) {
print("Hello, Closure!")
}
Run Code Online (Sandbox Code Playgroud)
或者如果避免保留循环:
button.add(for: .touchUpInside) { [unowned self] in
self.doStuff()
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
22915 次 |
| 最近记录: |