将 UIButton 连接到关闭?(迅速,目标行动)

Hooking up UIButton to closure? (Swift, target-action)(将 UIButton 连接到关闭?(迅速,目标行动))
本文介绍了将 UIButton 连接到关闭?(迅速,目标行动)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想将 UIButton 连接到一段代码——根据我的发现,在 Swift 中执行此操作的首选方法仍然是使用 addTarget(target: AnyObject?, action: Selector, forControlEvents: UIControlEvents) 函数.这使用 Selector 构造大概是为了向后兼容 Obj-C 库.我想我理解 Obj-C 中 @selector 的原因——能够引用方法,因为在 Obj-C 中方法不是一等值.

I want to hook up a UIButton to a piece of code – from what I have found, the preferred method to do this in Swift is still to use the addTarget(target: AnyObject?, action: Selector, forControlEvents: UIControlEvents) function. This uses the Selector construct presumably for backwards compatibility with Obj-C libraries. I think I understand the reason for @selector in Obj-C – being able to refer to a method since in Obj-C methods are not first-class values.

不过,在 Swift 中,函数是一等值.有没有办法将 UIButton 连接到闭包,类似于:

In Swift though, functions are first-class values. Is there a way to connect a UIButton to a closure, something similar to this:

// -- Some code here that sets up an object X

let buttonForObjectX = UIButton() 

// -- configure properties here of the button in regards to object
// -- for example title

buttonForObjectX.addAction(action: {() in 

  // this button is bound to object X, so do stuff relevant to X

}, forControlEvents: UIControlEvents.TouchUpOutside)

据我所知,上述情况目前是不可能的.考虑到 Swift 看起来它的目标是变得非常实用,这是为什么呢?这两个选项显然可以共存以实现向后兼容性.为什么这不像 JS 中的 onClick() 那样工作?似乎唯一将 UIButton 连接到目标-动作对的方法是使用仅出于向后兼容性原因而存在的东西(Selector).

To my knowledge, the above is currently not possible. Considering that Swift looks like it's aiming to be a quite functional, why is this? The two options could clearly co-exist for backwards compatibility. Why doesn't this work more like onClick() in JS? It seems that the only way to hook up a UIButton to a target-action pair is to use something that exists solely for backwards compatibility reasons (Selector).

我的用例是在循环中为不同的对象创建 UIButton,然后将每个对象连接到一个闭包.(设置标签/在字典中查找/子类化 UIButton 是肮脏的半解决方案,但我对如何在功能上做到这一点感兴趣,即这种关闭方法)

My use case is to create UIButtons in a loop for different objects, and then hook each up to a closure. (Setting a tag / looking up in a dictionary / subclassing UIButton are dirty semi-solutions, but I'm interested in how to do this functionally, ie this closure approach)

推荐答案

您可以通过添加辅助闭包包装器 (ClosureSleeve) 并将其作为关联对象添加到控件中来将 target-action 替换为闭包以使其保留.

You can replace target-action with a closure by adding a helper closure wrapper (ClosureSleeve) and adding it as an associated object to the control so it gets retained.

这与 n13 的答案中的解决方案类似.但我发现它更简单、更优雅.更直接地调用闭包并自动保留包装器(作为关联对象添加).

This is a similar solution to the one in n13's answer. But I find it simpler and more elegant. The closure is invoked more directly and the wrapper is automatically retained (added as an associated object).

class ClosureSleeve {
    let closure: () -> ()

    init(attachTo: AnyObject, closure: @escaping () -> ()) {
        self.closure = closure
        objc_setAssociatedObject(attachTo, "[(arc4random())]", self, .OBJC_ASSOCIATION_RETAIN)
    }

    @objc func invoke() {
        closure()
    }
}

extension UIControl {
    func addAction(for controlEvents: UIControlEvents = .primaryActionTriggered, action: @escaping () -> ()) {
        let sleeve = ClosureSleeve(attachTo: self, closure: action)
        addTarget(sleeve, action: #selector(ClosureSleeve.invoke), for: controlEvents)
    }
}

用法:

button.addAction {
    print("Hello")
}

它会自动挂钩到 .primaryActionTriggered 事件,该事件等于 UIButton 的 .touchUpInside.

It automatically hooks to the .primaryActionTriggered event which equals to .touchUpInside for UIButton.

这篇关于将 UIButton 连接到关闭?(迅速,目标行动)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!

相关文档推荐

Why local notification is not firing for UNCalendarNotificationTrigger(为什么没有为UNCalendarNotificationTrigger触发本地通知)
iOS VoiceOver functionality changes with Bundle Identifier(IOS画外音功能随捆绑包标识符而变化)
tabbar middle tab out of tabbar corner(选项卡栏中间的选项卡角外)
Pushing UIViewController above UITabBar(将UIView控制器推送到UITabBar上方)
Dropbox Files.download does not start when number of files in folder is gt; 1000(当文件夹中的文件数为1000时,Dropbox Files.Download不会启动)
How can I sync two flatList scroll position in react native(如何在本机Reaction中同步两个平面列表滚动位置)