如何创建多个缓存的 UIColor

How to create several cached UIColor

我的代码中有自定义颜色。我多次使用它们,但我希望它们只分配一次。

情况/问题

如果我们看一下 UIColor headers,我们可以看到以下内容:

[...]

// Some convenience methods to create colors.  These colors will be as calibrated as possible.
// These colors are cached.
  
open class var black: UIColor { get } // 0.0 white

open class var darkGray: UIColor { get } // 0.333 white

[...]

我创建了一个 extension 的 UIColor,如下所示:

import UIKit

extension UIColor {
    
    class func colorWithHexString(_ hex: String) -> UIColor {
        
        print("\(#function): \(hex)")
        
        // some code, then it return a UIColor

        return UIColor(
            red: CGFloat((rgbValue & 0xFF0000) >> 16) / 255.0,
            green: CGFloat((rgbValue & 0x00FF00) >> 8) / 255.0,
            blue: CGFloat(rgbValue & 0x0000FF) / 255.0,
            alpha: CGFloat(1.0)
        )

    }
    
    // Option A
    open class var myColorOne : UIColor {
        get {
            return colorWithHexString("AABBCC")
        }
    }
    
    // Option B
    class func myColorTwo() -> UIColor {
        return colorWithHexString("DDEEFF")
    }
}

从那里我可以很容易地使用我的颜色,有一个变量或一个函数。

// A
UIColor.myColorOne

// B
UIColor.myColorTwo()

遗憾的是,我对此并不完全满意。事实上,每次我想使用这些颜色时:都会进行新的 UIColor 分配。

我试过的

Apple 显然成功地缓存了他们的颜色。我自己也想这样做。我尝试了几种方法,但 none 似乎很理想。

1 - 使用 dispatch_once ✗

如 Swift 页面所示:免费功能 dispatch_once 在 Swift 中不再可用。

2 - 创建常量 (let) ✗

我收到以下错误:扩展可能不包含存储的属性

3 - 创建单例 ~

它确实适用于以下

(每种颜色只创建一次)
import UIKit

class Colors : UIColor {
    
    // Singleton
    static let sharedInstance = Colors()
    
    let myColorOne : UIColor = {
        return UIColor.colorWithHexString("AABBCC")
    }()
    
    let myColorTwo : UIColor = {
        return UIColor.colorWithHexString("DDEEFF")
    }()
    
}

但它迫使我再拥有一个文件并像这样命名我的颜色

Colors.sharedInstance.myColorOne

有没有办法像 Apple 一样获得我想要的颜色 UIColor.myColorOne 并缓存它们?

您可以像上面那样使用单例存储生成的 UIColor 值,并通过扩展 UIColor 并在其中放置访问权限来解决 Colors.sharedInstance.myColorOne 命名问题:

extension UIColor {
    class func myColorTwo() -> UIColor {
        return Colors.sharedInstance.myColorTwo
    }
}

可能有更好的方法,但使用全局变量(如评论中提到的 Grimxn)是解决问题的一种方法。

下面是一个示例,您可以将其复制并粘贴到 playground 中:

import UIKit

extension UIColor {

    class func colorWithHexString(_ hex: String) -> UIColor {
        print("allocate color")
        // do you conversion here...
        return UIColor.black
    }

}

private let myPrivateColorOne = UIColor.colorWithHexString("#ffffff")

extension UIColor {

    open class var myColorOne: UIColor {
        get {
            print("get color")
            return myPrivateColorOne
        }
    }

}

UIColor.myColorOne
UIColor.myColorOne

当您执行代码时,getter 将被调用两次,但 colorWithHexString 只会被调用一次。

您可以使用与 Using a dispatch_once singleton model in Swift,即静态 常量存储属性 它们被延迟初始化(并且只有一次)。这些都可以定义 直接在 UIColor 扩展中:

extension UIColor {
    convenience init(hex: String) {
        // ...          
    }

    static let myColorOne = UIColor(hex:"AABBCC")
    static let myColorTwo = UIColor(hex:"DDEEFF")
}

在Swift 3:

extension UIColor {
    class func color(hexString: String) -> UIColor {
        // ...
    }

    static let myColorOne = color(hexString: "AABBCC")
}