如何在Swift的Color扩展中避免重复计算components?
问题描述
我编写了如下的SwiftUI Color扩展:
extension Color { var cgColor: CGColor { resolve(in: .init()).cgColor } var r: Int { guard let components = cgColor.components, components.count == 4 else { return 0 } return Int(components[0] * 256) } var g: Int { guard let components = cgColor.components, components.count == 4 else { return 0 } return Int(components[1] * 256) } var b: Int { guard let components = cgColor.components, components.count == 4 else { return 0 } return Int(components[2] * 256) } var a: Double { guard let components = cgColor.components, components.count == 4 else { return 1 } return components[3] } }
目前r、g、b、a属性中都会重复获取并校验cgColor.components,请问如何在扩展内部避免这部分重复计算?我曾在使用该颜色的地方存储变量,但希望能在扩展内实现。
解决方案
可以通过提取私有计算属性来复用components的校验逻辑,将重复代码集中到一处,同时保持r/g/b/a属性的简洁性:
extension Color { var cgColor: CGColor { resolve(in: .init()).cgColor } // 私有计算属性,集中处理components的获取与校验 private var rgbaComponents: (r: CGFloat, g: CGFloat, b: CGFloat, a: CGFloat)? { guard let components = cgColor.components, components.count == 4 else { return nil } return (components[0], components[1], components[2], components[3]) } var r: Int { guard let components = rgbaComponents else { return 0 } return Int(components.r * 256) } var g: Int { guard let components = rgbaComponents else { return 0 } return Int(components.g * 256) } var b: Int { guard let components = rgbaComponents else { return 0 } return Int(components.b * 256) } var a: Double { guard let components = rgbaComponents else { return 1 } return Double(components.a) } }
优化说明
- 新增的
rgbaComponents私有属性承担了所有重复的逻辑:获取cgColor.components、校验组件数量是否为4,最终返回一个包含RGBA值的可选元组。 r/g/b/a属性只需判断rgbaComponents是否存在,直接从元组中取值计算即可,彻底消除了重复代码。- 这种方式既保持了扩展的内聚性,又提升了代码的可维护性——后续如果需要调整校验逻辑,只需修改
rgbaComponents一处即可。
内容的提问来源于stack exchange,提问作者rhroggtghsi
相关产品推荐
相关产品推荐

