【问题标题】:How to update custom classes properties properly?如何正确更新自定义类属性?
【发布时间】:2018-01-10 01:35:06
【问题描述】:

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

示例类:

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 类立即反映该更改。

我怎样才能做到这一点?

感谢您的宝贵时间。

【问题讨论】:

  • 与您的问题无关,但在覆盖 awakeFromNib 方法时必须调用 super.awakeFromNib()
  • fadedTextColor创建一个didSet,它会适当地更新其他内容
  • fadedTextColor 声明在哪里?它是您的 PopupButton 的属性吗?
  • stackoverflow.com/questions/38585344/… 有一个关于将事物移动到structenum 的论据以及在stackoverflow.com/questions/42050283/… 的另一个关于颜色(扩展名或结构)的论据,这取决于你在做什么,这些可能给你一个好的方向。
  • 我从来没有说过它会解决你的问题。您应该创建一个单例类,而不是将变量转储到文件中。

标签: ios swift custom-controls


【解决方案1】:

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

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
}

class PopupButton: UIButton {
    override func awakeFromNib() {
        super.awakeFromNib()
        layer.borderWidth = 1.3
        layer.borderColor = Shared.instance.fadedTextColor.cgColor
        layer.cornerRadius = 10
        layer.backgroundColor = UIColor.white.cgColor
        setTitleColor(Shared.instance.textHeaderColor, for: .normal)
        NotificationCenter.default.addObserver(self, selector: #selector(colorChanged), name: NSNotification.Name(rawValue: "fadedTextColorChanged"), object: nil)
    }
    @objc func colorChanged(notification: Notification) {
        layer.borderColor = Shared.instance.fadedTextColor.cgColor
    }
}

【讨论】:

  • 我会实施这个方法,然后回报你。谢谢@Leo Dabus。
  • 成功了,非常感谢!你认为,我应该把我所有的全局变量都放在这个 Shared 类中吗?
  • 我正在尝试将另一个实例添加到共享类中。例如,我将“实例”更改为“颜色”。现在我想添加“toggles”、“userDefault”等。我怎样才能做到这一点?
  • 那么在这种情况下,您需要创建另一个单例。就叫它Toggles.sharedInstance.whatever
  • 我明白了。我不能将它们放在同一个共享单例下。需要创建新的单例。非常感谢!
【解决方案2】:

斯威夫特 3

注意:此答案适用于 Swift 3。My other answer 利用了 Swift 4 中 much 更好的 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
            }
        }
    }
}

【讨论】:

  • 我相信你的方法也能完美运行。但是,我实现了 Leo 的方法并且工作正常。既然,我不像你那么优秀的程序员,我不想玩弄危及工作状态。我很感激你的时间。谢谢。
  • @sc13 并不是我真的介意你采用两种方法中的哪一种,但你的评论让我害怕。您正在使用源代码管理...对吗?
  • 能否详细说明源代码控制?
  • @sc13 版本控制?喜欢 Git 还是 SVN?哦,男孩,这吓到我了
  • @sc13 这是一款软件,可让您跟踪源代码(或任何文件,就此而言)随时间的变化,具有各种好处。它可以作为你的代码的备份,它可以帮助你调查一个错误最初是在哪个版本的软件中出现的,它可以更容易地与多个人在一个软件项目上协作,最重要的是(在我看来)是这样您就可以安全地进行实验性更改,因为您知道存在可以随时回滚的工作状态。
【解决方案3】:

斯威夫特 4

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

有关详细信息,请观看 WWDC 2017 的 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)
        })
    }
}

【讨论】:

    猜你喜欢
    • 2020-02-13
    • 1970-01-01
    • 2014-11-05
    • 1970-01-01
    • 2016-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-21
    相关资源
    最近更新 更多