在 Swift 中缓存静态函数结果?

Cache static function result in Swift?

我有一个生成 UIColor 对象的静态函数,因此它可以在整个应用程序中多次重复使用。我不希望此代码每次都 运行,但实际上只是第一次并将其放入缓存,然后让任何后续检索从缓存中获取它。唯一需要注意的是这个值可以改变,所以我不想永久保存这个值,而只是将它保存到内存中,这样如果应用程序重新启动,它将获取最新的值并在其整个生命周期中使用它。

我的函数如下所示:

class AppConfig: NSObject {   
    static func getGlobalTintColor(alpha: Float = 1) -> UIColor! {
        let colors = split(someVarFromInfoPlist) { [=11=] == "," }
        let red = CGFloat(colors[0].toInt() ?? 0) / CGFloat(255)
        let green = CGFloat(colors[1].toInt() ?? 0) / CGFloat(255)
        let blue = CGFloat(colors[2].toInt() ?? 0) / CGFloat(255)
        return UIColor(red: red, green: green, blue: blue, alpha: CGFloat(alpha))
    }
}

我不想每次都getGlobalTintColor到运行那个逻辑。那么如何在第一次缓存它并让它在应用程序的其余生命周期中提供服务?

您描述的是 static 变量 而不是 函数 。为变量提供一个创建颜色的初始化函数。

class AppConfig: NSObject {
    static var alpha : CGFloat = 1
    static var globalTintColor : UIColor = {
        // figure out color once, possibly based on `alpha`
        return theColor
    }()
}

这是有效的,因为静态 var 初始化器是 lazy;它可能取决于您的 alpha 并且在您第一次实际询问它的值之前它不会被初始化。此外,初始化函数 之后不会 运行 再次 (除非您退出并重新启动该应用程序),这正是您要寻找的。

可能是这样的:

class AppConfig: NSObject {   
    private static var tintColor: UIColor?

    static func getGlobalTintColor(alpha: Float = 1) -> UIColor! {
        if tintColor == nil {
            let colors = split(someVarFromInfoPlist) { [=10=] == "," }
            let red = CGFloat(colors[0].toInt() ?? 0) / CGFloat(255)
            let green = CGFloat(colors[1].toInt() ?? 0) / CGFloat(255)
            let blue = CGFloat(colors[2].toInt() ?? 0) / CGFloat(255)
            tintColor = UIColor(red: red, green: green, blue: blue, alpha: CGFloat(alpha))
        }
        return tintColor!.colorWithAlphaComponent(CGFloat(alpha))
    }
}

您可以创建一个函数 returning 一个函数,将其 return 值缓存到 属性 中,然后调用存储在该 属性 中的函数来计算实际颜色取决于 alpha。

这是 "caching" 函数:

private static func _getGlobalTintColor() -> (Float) -> UIColor {
    let colors = split(someVarFromInfoPlist) { [=10=] == "," }
    let red = CGFloat(colors[0].toInt() ?? 0) / CGFloat(255)
    let green = CGFloat(colors[1].toInt() ?? 0) / CGFloat(255)
    let blue = CGFloat(colors[2].toInt() ?? 0) / CGFloat(255)
    return { alpha in UIColor(red: red, green: green, blue: blue, alpha: CGFloat(alpha)) }
}

如您所见,它 return 是一个具有签名 (Float) -> UIColor 的函数,即将 alpha 作为参数并 return 设置颜色。

接下来,使用此函数的 return 值初始化静态 属性:

private static let globalColor = AppConfig._getGlobalTintColor()

最后,公开的静态函数接受一个 alpha 参数,并调用存储在该 属性 中的函数来获取和 return 颜色:

static func getGlobalTintColor(alpha: Float = 1) -> UIColor {
    return self.globalColor(alpha)
}

请注意,可以删除第一个私有函数,并使用内联闭包初始化 属性:

class AppConfig: NSObject {
    private static let globalColor: Float -> UIColor = {
        let colors = split(someVarFromInfoPlist) { [=13=] == "," }
        let red = CGFloat(colors[0].toInt() ?? 0) / CGFloat(255)
        let green = CGFloat(colors[1].toInt() ?? 0) / CGFloat(255)
        let blue = CGFloat(colors[2].toInt() ?? 0) / CGFloat(255)
        return { alpha in UIColor(red: red, green: green, blue: blue, alpha: CGFloat(alpha)) }
    }()

    static func getGlobalTintColor(alpha: Float = 1) -> UIColor {
        return self.globalColor(alpha)
    }
}

假设 alpha 输入在整个应用程序中可能不同,您可以考虑使用 NSCache,其中键是由颜色和 alpha 形成的字符串,值是包装在 holder NSObject 子类中的 UIColor。

https://developer.apple.com/library/ios/documentation/Cocoa/Reference/NSCache_Class/

NSCache 将声明为:

private static let cache = NSCache()

我建议拆分为具有固定 alpha 的惰性 static 常量和一个单独的函数来指定 alpha:

class AppConfig: NSObject {    
    static let globalTintColor: UIColor = {
        let colors = split(someVarFromInfoPlist) { [=10=] == "," }
        let red = CGFloat(colors[0].toInt() ?? 0) / CGFloat(255)
        let green = CGFloat(colors[1].toInt() ?? 0) / CGFloat(255)
        let blue = CGFloat(colors[2].toInt() ?? 0) / CGFloat(255)
        return UIColor(red: red, green: green, blue: blue, alpha: 1)
    }()

    static func globalTintColor(alpha: CGFloat) -> UIColor {
        return globalTintColor.colorWithAlphaComponent(alpha)
    }
}