快速将闭包作为参数传递给函数中的选择器 [英] Passing closure in swift as parameter to be used by selector in function

查看:72
本文介绍了快速将闭包作为参数传递给函数中的选择器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试创建一个通用的按钮创建函数,在该函数中传递一个闭合值,该闭合值表示单击按钮后所产生的操作.我的代码如下.但是,出现以下错误: #selector的参数不能引用属性.有任何解决方法的建议吗?除了目标操作之外,我不想编写其他功能都相同的单独函数.

I am trying to create a generic button creation function into which I pass a closure that represents the action that results as a result of clicking on the button. My code is below. However, I get the following error: Argument of #selector cannot refer to property. Any suggestions for a workaround ? I don't want to write separate functions for which everything else is the same except for the target action.

 func myButton(textColor tColor:UIColor , title:String, 
                 _ buttonFcn: (UIButton) -> Void,   
                 titleSize:CGFloat=30) -> UIButton {
    let newButton = UIButton(type: .System)
    let bgColor = UIColor(red:204/255, green:204/255, blue:204/255, alpha:1.0)
    newButton.backgroundColor = bgColor

    newButton.setTitle(title, forState: .Normal)
    newButton.setTitleColor(tColor, forState: .Normal)

    newButton.titleLabel?.font = newButton.titleLabel?.font.fontWithSize(titleSize)


    newButton.addTarget(self,  action:#selector(buttonFcn),
                        forControlEvents: 
                           UIControlEvents.TouchUpInside)

    return newButton
}

推荐答案

问题是目标动作机制是Objective-C机制,因此基于动作选择器是方法的观念 .因此,您需要具有一些基于NSObject的 object ,该对象具有此功能,作为方法,然后可以用作目标.

The problem is that the target-action mechanism is an Objective-C mechanism, and therefore is predicated on the notion that the action selector is a method of an object. You need, therefore, to have some NSObject-based object that has this function as a method, and which can then serve as the target.

因此,如果在每种情况下目标和操作都不同,则您需要传递的是对目标的引用以及选择器 string . Swift会对此s之以鼻,但是,如果您知道如何正确形成选择器字符串,那么您当然可以摆脱它.您将无法使用#selector语法,因此,如果您错误地形成选择器字符串,则可能会崩溃.但这是我们在过去的Objective-C时代一直做的事情,因此,如果那是您的目标,那就快走吧.

Thus, if what differs in every case is the target and the action, what you need to pass is a reference to the target along with the selector string. Swift will squawk at this, but if you know how to form a selector string correctly you can certainly get away with it; you just won't be able to use the #selector syntax, and so you will risk crashing if you form the selector string incorrectly. But it's the kind of thing we used to do all the time in the old Objective-C days, so go right ahead if that's your aim.

完全人工但可行的示例:

Totally artificial but working example:

func buttonMaker(target:NSObject, selectorString:String) -> UIButton {
    let b = UIButton(type:.system)
    b.setTitle("Testing", for: .normal)
    b.addTarget(target, action: Selector(selectorString), for: .touchUpInside)
    b.sizeToFit()
    return b
}

这是从视图控制器调用它的方法:

And here's how to call it from a view controller:

func doButton(_ sender:Any) {
    print("ha!")
}

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    let b = buttonMaker(target:self, selectorString:"doButton:")
    b.frame.origin = CGPoint(x:100, y:100)
    self.view.addSubview(b)
}

当我们点击按钮时,我们不会崩溃(而是打印"ha"),因为我知道如何正确制作选择器字符串.但是,正如您所看到的,要实现此目的,我必须完全放弃使用#selector,因此安全性不在讨论之列.如果我输入的选择器字符串不正确-例如,如果我拼写错误或省略了冒号-我们将在按钮点击时崩溃,就像我们在Swift #selector和Objective-之前一直都是这样- C @selector发明了.

And when we tap the button, we don't crash (rather, we print "ha"), because I know how to make selector strings correctly. But, as you can see, to accomplish this I had to give up the use of #selector altogether, so safety is out the window. If I had written my selector string incorrectly — for instance, if I had spelled it wrong, or omitted the colon — we'd have crashed on the button tap, just like we used to all the time before Swift #selector and Objective-C @selector were invented.

这篇关于快速将闭包作为参数传递给函数中的选择器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆