在 Swift 中使用 Bool 的视图控制器扩展

Extension for view controller using Bool in Swift

我正在尝试对视图控制器进行扩展。这是带有点击识别器的简单视图。如果按下一次,背景颜色应该从品红色变为橙色。到下一次推送时,它应该会再次变成洋红色。

如果我为具体 VC 做这件事,比方说,开始 VC,它会起作用。这是代码:

import UIKit

class StartVC: UIViewController {
    // bool
    var colorChanged = false

    override func viewDidLoad() {
        super.viewDidLoad()

        view.backgroundColor = UIColor.magenta
        setMyTouchableView2()
    }
}

extension StartVC {
    // make touchable view
    func setMyTouchableView2() {
        let myView = UIImageView(frame: CGRect(x: 100, y: 100, width: 50, height: 50))
        myView.backgroundColor = UIColor.yellow

        // add gesture recognizer
        let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(changeColor2(_:)))
        myView.addGestureRecognizer(tapGestureRecognizer)
        myView.isUserInteractionEnabled = true

        view.addSubview(myView)
    }

    func changeColor2(_ recognizer:UITapGestureRecognizer){
        if(colorChanged) {
            view.backgroundColor = UIColor.magenta
        } else {
            view.backgroundColor = UIColor.orange
        }

        colorChanged = !colorChanged
    }
}

但是如果我尝试将此扩展推广到任何视图控制器,我会遇到以下问题:我无法将布尔值 (colorChanged) 放入视图控制器中,因为扩展看不到它。我该如何解决?

代码如下:

import UIKit

class ViewController: UIViewController {
    // bool
    var colorChanged = false

    override func viewDidLoad() {
        super.viewDidLoad()

        view.backgroundColor = UIColor.magenta
        setMyTouchableView()
    }
}

extension UIViewController {
    // make touchable view
    func setMyTouchableView() {
        let myView = UIImageView(frame: CGRect(x: 100, y: 100, width: 50, height: 50))
        myView.backgroundColor = UIColor.yellow

        // add gesture recognizer
        let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(changeColor(_:)))
        myView.addGestureRecognizer(tapGestureRecognizer)
        myView.isUserInteractionEnabled = true

        view.addSubview(myView)
    }

    func changeColor(_ recognizer:UITapGestureRecognizer){
        if(colorChanged) {
            view.backgroundColor = UIColor.magenta
        } else {
            view.backgroundColor = UIColor.orange
        }
    }

扩展不能默认存储 属性。但是,如果你真的需要它,你可以通过 objc runtime

创建它
private var associationKey: UInt8 = 111 // Some constant

extension ViewController {
    var colorChanged: Bool {
        get {
            return objc_getAssociatedObject(self, &associationKey) as! Bool
        }
        set {
            objc_setAssociatedObject(self, &associationKey, newValue, .OBJC_ASSOCIATION_ASSIGN)
        }
    }
}

但是您可能会遇到一个问题,即多个控制器会更改此标志。所以你也可以尝试使用 protocols

protocol ColorChangable {
    var colorChange: Bool { get set }
}

extension ColorChangable where Self: UIViewController {
    func setMyTouchableView {
        // Your logic
    }
}

class ViewController: UIViewController {
    var colorChange: Bool

    func viewDidLoad() {
        self.viewDidLoad()

        setMyTouchableView()
    }
}

extension ViewController: ColorChangable {}

可以用struct做一个全局变量-

   struct GlobalStruct {
    static var colorChanged = false
}

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        view.backgroundColor = UIColor.magenta
        setMyTouchableView()
    }
}

extension UIViewController {
    // make touchable view
    func setMyTouchableView() {
        let myView = UIImageView(frame: CGRect(x: 100, y: 100, width: 50, height: 50))
        myView.backgroundColor = UIColor.yellow

        // add gesture recognizer
        let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(changeColor(_:)))
        myView.addGestureRecognizer(tapGestureRecognizer)
        myView.isUserInteractionEnabled = true

        view.addSubview(myView)
    }

    func changeColor(_ recognizer:UITapGestureRecognizer){
        if(GlobalStruct.colorChanged) {
            view.backgroundColor = UIColor.magenta
        } else {
            view.backgroundColor = UIColor.orange
        }
    }
}