我正在尝试创建一个通用按钮创建功能,我在其中传递一个闭包,该闭包表示由于单击按钮而产生的操作。我的代码如下。但是,我收到以下错误: #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
}
答案 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
被发明了。