将swift中的闭包作为参数传递给函数中的选择器

时间:2017-03-20 03:24:35

标签: ios swift

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

 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
}

1 个答案:

答案 0 :(得分:2)

问题在于目标 - 动作机制是一种Objective-C机制,因此基于动作选择器是对象 方法的概念。 。因此,您需要具有一些基于NSObject的对象,它具有此函数作为方法,然后可以作为目标。

因此,如果目标和动作在每种情况下都有所不同,那么您需要传递的是对目标的引用以及选择器 string 。斯威夫特会对此嗤之以鼻,但如果你知道如何正确地形成一个选择器字符串,你肯定可以逃脱它;您将无法使用#selector语法,因此如果您错误地形成选择器字符串,您将面临崩溃的风险。但这是我们过去常常在旧的Objective-C时代做的事情,所以如果这是你的目标,请继续前进。

完全人为但又有效的例子:

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
}

以下是如何从视图控制器调用它:

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被发明了。