Swift 4 - 为多个按钮创建通用功能

Swift 4 - Creating a common function for multiple buttons

我想知道是否有更有效的方法来编写一个除了按下哪个按钮以及它与结构中的哪个项目相关之外相同的操作。基本上,我有一个包含 10 个变量的结构,所有变量都是布尔类型,并且我有 10 个按钮。当用户按下按钮时,我想检查它是否已经被按下(使用结构),然后根据状态更改按钮的背景并反转状态。我已经复制了其中一个按钮的当前代码,但我认为我应该能够避免这样做 10 次!

@IBAction func architectureButtonPressed(_ sender: Any) {

        if myInterests.architecture {

             myInterests.architecture = false
             architectureButton.setBackgroundImage(imageUncheckedNarrow, for: .normal)

        } else {

            myInterests.architecture = true
            architectureButton.setBackgroundImage(imageCheckedNarrow, for: .normal)
        }


    }

嗯,一种简单的方法是让每个 UIButton 指向相同的 architectureButtonPressed IBAction 方法。由于按下的按钮被传递到方法(发件人)中,您可以查阅它的标签 属性 以了解应更新结构中哪个字段的索引。 (然后您可能想更改您的结构以仅存储 10 个布尔值的数组,但这取决于您)。

然后对于每个 UIButton,无论是在情节提要中还是在 nib 中以编程方式,您都将适当的索引值分配给按钮的标记字段。

  1. 为每个按钮创建您的 IBOutlet

  2. 创建一个数组并存储所有按钮,如:var arrayButtons : [UIButton] = []

    arrayButtons.append[按钮 1]

    arrayButtons.append[按钮2]

    ...

  3. 创建一个布尔数组来存储 true/false: var arrayBools : [Bool] = [] 并初始化一些值。

请注意,arrayButtons 和 arrayBools 的索引必须相同。

  1. 创建选择器函数来监听触摸按钮。

    button.addTarget(self, action: #selector(my_func), for: .touchUpInside)
    
    @objc func my_func(_ sender : UIButton) {
    
    for i in 0...arrayButtons.size-1 {
        if arrayButtons[i] == sender {
            if arrayBooleans[i] {
                arrayBooleans[i] = false
                arrayButtons[i].setImage()
            } else {
                arrayBooleans[i] = true
                arrayButtons[i].setImage()
            }
        }
      }
    }
    

我的建议是通过 State Config 管理 Interface Builder 中的图像 (Default/Selected)

然后为每个按钮分配一个从100开始的唯一标签,并在switch语句中将IBAction中的isSelected值设置为相应的结构成员:

@IBAction func buttonPressed(_ sender: UIButton) {
    switch sender.tag {
    case 100: myInterests.architecture = sender.isSelected
    case 101: myInterests.art = sender.isSelected

    ...
    default: break
    }

}

或者将 Swift 的原生 KVC 与 WriteableKeypath

结合使用
let keypaths : [WritableKeyPath<Interests,Bool>] = [\.architecture, \.art, \.fashion, \.history, \.localCulture, \.music, \.nature, \.shopping, \.sport, \.anything]

@IBAction func buttonPressed(_ sender: UIButton) {
    let index = sender.tag - 100
    let keypath = keypaths[index]
    myInterests[keyPath: keypath] = sender.isSelected
}