【问题标题】:Extension for view controller using Bool in Swift在 Swift 中使用 Bool 扩展视图控制器
【发布时间】:2018-02-22 22:30:36
【问题描述】:

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

如果我为具体的 VC 做这件事,比如说 StartVC,它就可以工作。代码如下:

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
        }
    }

【问题讨论】:

  • 如何将“colorChanged”变量作为参数传递给 changeColor() ?
  • 您也可以将测试条件更改为“如果 view.backgroundColor == UIColor.magenta”更改为橙色,反之亦然
  • 类当然可以覆盖超类的方法,但是你不能使用扩展。扩展中的方法或属性不能与原始类中的方法或属性同名。
  • 我试过了:它永远不会被执行。
  • 致 Sneha:我都试过了。它永远不会被执行,颜色也不会改变。

标签: ios swift boolean extension-methods viewcontroller


【解决方案1】:

默认情况下,扩展不能具有存储属性。但是,如果你真的需要这个,你可以通过 objc 运行时创建它

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)
        }
    }
}

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

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 {}

【讨论】:

    【解决方案2】:

    你可以使用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
            }
        }
    }
    

    【讨论】:

    • 好主意。但我现在试了一下:它只工作一次。据我所知,你不能重复它。
    • 你必须像 GlobalStruct.colorChanged = true 这样根据需要更改颜色。
    • 是的!我必须添加: GlobalStruct.colorChanged = !GlobalStruct.colorChanged。现在它起作用了。非常感谢您的帮助!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-05-24
    • 2017-10-02
    • 1970-01-01
    • 1970-01-01
    • 2017-02-02
    • 1970-01-01
    • 2016-12-23
    相关资源
    最近更新 更多