2

I was adding a target to a UIButton for my letterTapped() function like this:

button.addTarget(self, action: "letterTapped:", forControlEvents: .TouchUpInside)

I like how .TouchUpInside works with autocompletion and it looks neater and seems safer than the string I'm supposed to use for the action: parameter. So I searched and found this tutorial which uses enums to replace "magic strings".

I created an enum like this:

    enum functionForAction: Selector {

    case clearTapped = "clearTapped:"
    case submitTapped = "submitTapped:"
    case letterTapped = "letterTapped:"

}

Then I use it like this:

 button.addTarget(self, action: functionForAction.letterTapped.rawValue, forControlEvents: .TouchUpInside)

I get code completion and I'm never trying to call a misspelled selector. Feels better. But is it possible to improve it? I'd really just like to type this:

 button.addTarget(self, action: .letterTapped, forControlEvents: .TouchUpInside)

Can enums make this happen for me in Swift?

4

1 回答 1

1

有两种方法可以做到这一点,虽然可以得到你想要的语法,但我认为第二种方法很可能是更好的方法。

为了做你想做的事,我们将像你一样创建一个枚举,但也会向UIControl(UIButton的超类) 添加一个扩展,以便我们可以使用 addTargetControlSelector

enum ControlSelector: Selector {
    case ClearTapped = "clearTapped:"
    case SubmitTapped = "submitTapped:"
    case LetterTapped = "letterTapped:"
}

extension UIControl {
    func addTarget(target: AnyObject?, action: ControlSelector, forControlEvents controlEvents: UIControlEvents) {
        addTarget(target, action: action.rawValue, forControlEvents: controlEvents)
    }
}

现在我们可以addTarget使用您喜欢的语法调用:

button.addTarget(self, action: .ClearTapped, forControlEvents: .TouchUpInside)

(顺便说一下,按照惯例,枚举的第一个字母通常是大写字母,这就是为什么我从你的代码中稍微改变了它。)

但是,这可能会变得混乱,除非您希望ControlSelector在所有代码之间共享枚举(现在,让选择器更清晰有什么意义)?要使这项工作适用于所有代码,您要么必须保持两者的访问级别为公开,要么UIControl在您希望以这种方式编写内容的每个文件中写入扩展名。

我建议改为使用私有类来保持选择器清晰。

private class ControlSelector {
    static var clearTapped: Selector = "clearTapped:"
    static var submitTapped: Selector = "submitTapped:"
    static var letterTapped: Selector = "letterTapped:"
}

然后,您将不再需要协议扩展,而是addTarget以这种方式调用您的方法:

button.addTarget(self, action: ControlSelector.clearTapped, forControlEvents: .TouchUpInside)

希望这可以帮助!

于 2016-02-07T04:28:26.930 回答