Swift像闭包一样使用select器参数
我只是想知道是否有可能将一个函数传递给一个button操作(通常是一个select器)。
例如,通常我会说:
UIBarButtonItem(title: "Press", style: .Done, target: self, action: "functionToCall") func functionToCall() { // Do something }
但我想知道是否有可能做到这样的事情:
UIBarButtonItem(title: "Press", style: .Done, target: self, action: { // Do Something })
我想这样做的原因是因为我的function是非常简单的,看起来它会更整洁,更像Swift,就像他们将重点放在closures上一样。
这是Swift 3的一个更新的解决scheme。
class BlockBarButtonItem: UIBarButtonItem { private var actionHandler: ((Void) -> Void)? convenience init(title: String?, style: UIBarButtonItemStyle, actionHandler: ((Void) -> Void)?) { self.init(title: title, style: style, target: nil, action: #selector(barButtonItemPressed)) self.target = self self.actionHandler = actionHandler } convenience init(image: UIImage?, style: UIBarButtonItemStyle, actionHandler: ((Void) -> Void)?) { self.init(image: image, style: style, target: nil, action: #selector(barButtonItemPressed)) self.target = self self.actionHandler = actionHandler } func barButtonItemPressed(sender: UIBarButtonItem) { actionHandler?() } }
这是一个没有子类别的替代解决scheme:
extension UIBarButtonItem { private struct AssociatedObject { static var key = "action_closure_key" } var actionClosure: (()->Void)? { get { return objc_getAssociatedObject(self, &AssociatedObject.key) as? ()->Void } set { objc_setAssociatedObject(self, &AssociatedObject.key, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) target = self action = #selector(didTapButton(sender:)) } } @objc func didTapButton(sender: Any) { actionClosure?() } }
它依靠Objective-C运行时的关联对象来添加一个闭包/块属性。
设置时,它将目标更改为自身,并将select器指向一个调用闭包(如果存在)的新函数。
有了这个,在任何时候你可以设置任何UIBarButtonItem
并期望一切工作,这里是一个例子:
let button = UIBarButtonItem( barButtonSystemItem: .action, target: nil, action: nil ) button.actionClosure = { print("hello") }
Reddit上的一篇文章解释了一个自定义组件的解决scheme – https://www.reddit.com/r/swift/comments/3fjzap/creating_button_action_programatically_using
要使用它,虽然我不得不通过编程添加button,而不是通过故事板。 这是我是如何做到的。
let tempVariableIWantToReference = "Classy" navigationTitle.leftBarButtonItem = BlockBarButtonItem.init( title: "< Back", style: UIBarButtonItemStyle.Plain, actionHandler: { () -> Void in print("Hey I'm in a closure") print("I can even reference temporary variables. \(self.tempVariableIWantToReference)!!!") })
不幸的是,苹果公司提供的初始设备是不可能的。 在后台工作的方式是使用reflection,提供一个闭包是完全不同的东西,目前不支持。
您可能可以通过一些黑客手段创build自定义解决scheme,或者将来可能会引入Apple。