如何正确更新自定义类属性?

时间:2018-01-10 01:35:07

标签: ios swift custom-controls

我有标签,按钮,视图等的自定义类。

示例类:

class PopupButton: UIButton {
    override func awakeFromNib() {
        self.layer.borderWidth = 1.3
        self.layer.borderColor = fadedTextColor.cgColor
        self.layer.cornerRadius = 10
        self.layer.backgroundColor = whiteColor.cgColor
        self.setTitleColor(textHeaderColor, for: .normal)
    }
}

当我更改颜色即:fadedTextColor时,我希望此PopupButton类能够立即反映该更改。

我怎样才能做到这一点?

感谢您的时间。

3 个答案:

答案 0 :(得分:1)

首先,您创建一个单例类来保存所有“全局”变量。然后将didSet添加到fadedTextColor属性以在其值更改时发布通知。接下来在自定义类中添加一个观察者和一个选择器,使用单例类中的颜色更改按钮边框颜色:

colfunc <- colorRampPalette(c("red", "blue"))
colfunc(10)
class Shared {
    private init() {}
    static let instance = Shared()
    var fadedTextColor: UIColor = .red {
        didSet {
            NotificationCenter.default.post(name: NSNotification.Name(rawValue: "fadedTextColorChanged"), object: nil)
        }
    }
    var textHeaderColor: UIColor = .blue
}

答案 1 :(得分:0)

Swift 3

注意:这个答案适用于Swift 3. My other answer利用Swift 4中更好的API。

我会为此目的使用键值观察。它具有使用标准化#keyPath字符串来识别更改而不是通知的任意字符串的良好属性。

[.initial, .new]选项使得observeValue(forKeyPath:of:change:context:)立即为您调用(设置初始值),并在每次更改后(通知新值)。

public final class AppConfig: NSObject {
    static let shared = AppConfig()
    override private init() {}

    @objc dynamic var fadedTextColor: UIColor = .red
    @objc dynamic var textHeaderColor: UIColor = .blue
    // ... add other global config state properties here
    // any pro properties you wish to observe must be `@objc` and ` dynamic`
}

class PopupButton: UIButton {
    override func awakeFromNib() {
        let appconfig = AppConfig.shared

        self.layer.borderWidth = 1.3

        appconfig.addObserver(self,
                              forKeyPath: #keyPath(AppConfig.fadedTextColor),
                              options: [.initial, .new], context: nil)
        self.layer.cornerRadius = 10
        self.layer.backgroundColor = UIColor.white.cgColor


        appconfig.addObserver(self,
                              forKeyPath: #keyPath(AppConfig.textHeaderColor),
                              options: [.initial, .new], context: nil)



    }

    override func observeValue(
        forKeyPath keyPath: String?,
        of object: Any?,
        change: [NSKeyValueChangeKey : Any]?,
        context: UnsafeMutableRawPointer?) {
        guard let keyPath = keyPath, let newValue = change?[.newKey] else { return }

        if object as? AppConfig == AppConfig.shared {
            switch (keyPath, newValue) {
            case (#keyPath(AppConfig.fadedTextColor), let fadedTextColor as UIColor):
                self.layer.borderColor = fadedTextColor.cgColor

            case (#keyPath(AppConfig.textHeaderColor), let textHeaderColor as UIColor):
                self.setTitleColor(textHeaderColor, for: .normal)

            // Handle other changes here

            default: break
            }
        }
    }
}

答案 2 :(得分:0)

Swift 4

我们在Swift 4中有一个非常好但文档很差的API,它使用KeyPath来实现简洁,类型安全的键值观察。需要处理所有回调的大量observeValue(forKeyPath:of:change:context:)已经不复存在了。相反,每个观察都采用一个闭包,只有在与它有关的事件发生时才会调用。这很好地打破了你的observeValue(forKeyPath:of:change:context:)方法。

有关详细信息,请参阅2017年WWDC的What's New in Foundation视频,从19:30开始。

public final class AppConfig: NSObject {
    static let shared = AppConfig()
    override private init() {}

    @objc dynamic var fadedTextColor: UIColor = .red
    @objc dynamic var textHeaderColor: UIColor = .blue
    // ... add other global config state properties here
    // any pro properties you wish to observe must be `@objc` and ` dynamic`
}

import UIKit

class PopupButton: UIButton {
    var observers = [NSKeyValueObservation]()

    override func awakeFromNib() {
        let appconfig = AppConfig.shared

        self.layer.borderWidth = 1.3

        observers.append(appconfig.observe(\.fadedTextColor,  options: [.initial, .new]) { object, change in
            self.layer.borderColor = object.fadedTextColor.cgColor
        })
        self.layer.cornerRadius = 10
        self.layer.backgroundColor = UIColor.white.cgColor


        observers.append(appconfig.observe(\.textHeaderColor,  options: [.initial, .new]) { object, change in
            self.setTitleColor(object.textHeaderColor, for: .normal)
        })
    }
}