如何在Swift扩展中遍历可用UIColor类方法以获取颜色数组?
自动获取UIColor扩展中的所有自定义颜色
嘿,这个需求挺实用的!要实现这种“自动化抓取扩展里所有颜色”的功能,Swift本身的反射API在处理类方法时有点局限,但我们可以借助**Objective-C运行时(Runtime)**来搞定,它能帮我们遍历类的所有方法,筛选出我们需要的自定义颜色方法。
先理清楚核心思路
你的UIColor扩展里的方法都是类方法,且返回UIColor类型,参数只有可选的alpha。我们的目标是:
- 让这些方法能被Runtime识别(需要给方法加
@objc标记) - 遍历UIColor的所有类方法,筛选出自定义的那些(排除系统自带的颜色方法)
- 调用这些方法获取颜色实例,组成数组返回
具体实现步骤
1. 给你的UIColor扩展方法添加@objc标记
Runtime只能识别暴露给Objective-C的方法,所以我们需要给每个自定义颜色方法加上@objc:
extension UIColor { @objc class func firstColor(alpha: CGFloat = 1.0) -> UIColor { // 注意:你原代码里的green(322)和blue(405)超过了255,这里帮你修正为合理值,避免显示白色 return UIColor(red: 139.0/255.0, green: 222.0/255.0, blue: 205.0/255.0, alpha: alpha) } @objc class func secondColor(alpha: CGFloat = 1.0) -> UIColor { return UIColor(red: 225.0/255.0, green: 139.0/255.0, blue: 127.0/255.0, alpha: alpha) } }
2. 编写你的“magicalFunctionHere”
这个函数会用Runtime遍历方法,筛选并调用自定义颜色方法:
import Foundation func getCustomUIColors() -> [UIColor] { var methodCount: UInt32 = 0 // 获取UIColor类的所有类方法 let methods = class_copyMethodList(object_getClass(UIColor.self), &methodCount) // 记得释放内存,避免泄漏 defer { free(methods) } var availableColors = [UIColor]() guard let methodList = methods else { return availableColors } for i in 0..<Int(methodCount) { let method = methodList[i] let selector = method_getName(method) let methodName = String(cString: sel_getName(selector)) // 筛选逻辑:只保留以"Color"结尾,且不是系统自带的颜色方法 // 你可以根据自己的命名规则调整,比如给方法加特定前缀(如"custom_"),这样筛选更精准 let systemColorMethods = ["clearColor", "whiteColor", "blackColor", "grayColor", "lightGrayColor", "darkGrayColor", "redColor", "greenColor", "blueColor", "cyanColor", "yellowColor", "magentaColor", "orangeColor", "purpleColor", "brownColor"] guard methodName.hasSuffix("Color"), !systemColorMethods.contains(methodName) else { continue } // 调用方法获取颜色(因为我们的方法有默认alpha参数,所以无参调用也能生效) if let color = UIColor.perform(selector).takeUnretainedValue() as? UIColor { availableColors.append(color) } } return availableColors }
3. 使用示例
现在你就能像期望的那样获取所有自定义颜色了:
let availableColors: [UIColor] = getCustomUIColors()
备选方案(无需Runtime)
如果你不想依赖Runtime,也可以手动维护一个Selector数组,虽然不够自动化,但胜在简单直接:
// 每次新增颜色方法,都要把Selector加到这个数组里 let customColorSelectors: [Selector] = [#selector(UIColor.firstColor), #selector(UIColor.secondColor)] let availableColors = customColorSelectors.compactMap { UIColor.perform($0).takeUnretainedValue() as? UIColor }
注意事项
- 如果你自定义的颜色方法有不同的参数(比如有的需要额外参数),那Runtime的调用逻辑需要调整,得先检查方法的参数个数和类型,再传递对应参数调用。
- 命名规则很重要:如果你的自定义方法命名和系统方法冲突,筛选逻辑会出错,所以建议给自定义方法加统一前缀(比如
custom_firstColor),这样筛选时只需要检查前缀即可,更可靠。
内容的提问来源于stack exchange,提问作者drew..
相关产品推荐
相关产品推荐

