You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为多个Swift枚举编写复用DRY函数?代码优化问询

解决方案:协议+协议扩展实现复用

当然可以!其实用协议+协议扩展就能完美解决这个问题,既符合Swift的设计模式,又能彻底避免重复代码,完全遵循DRY原则。

具体步骤:

  1. 定义一个带约束的协议
    我们先创建一个协议,它继承自CaseIterable(这样能直接使用allCases),同时要求每个枚举 case 必须实现title计算属性:

    protocol CaseIterableWithTitle: CaseIterable {
        var title: String { get }
    }
    
  2. 给协议添加默认实现
    接下来给这个协议扩展,统一实现titles静态属性的逻辑——这部分就是你之前重复写的循环,现在只需要写一次:

    extension CaseIterableWithTitle {
        static var titles: [String] {
            // 用map替代手动循环,代码更简洁
            allCases.map { $0.title }
        }
    }
    
  3. 修改现有枚举,遵循协议
    现在只需要让你的枚举遵循CaseIterableWithTitle协议,同时保留各自的title实现(毕竟每个枚举的标题逻辑是独有的),去掉重复的titles属性即可:

    enum CustomerTypes: Int, CaseIterableWithTitle {
        case NewCustomer = 0
        case ExistingCustomer
        case Myself
        
        var title: String {
            switch self {
            case .NewCustomer: return StandardStrings.NewDrive.NewCustomer.string
            case .ExistingCustomer: return StandardStrings.NewDrive.ExistingCustomer.string
            case .Myself: return StandardStrings.NewDrive.Myself.string
            }
        }
    }
    
    enum EnquiryTypes: Int, CaseIterableWithTitle {
        case Phone = 0
        case FaceToFace
        
        var title: String {
            switch self {
            case .Phone: return StandardStrings.Misc.Phone.string
            case .FaceToFace: return StandardStrings.Misc.FaceToFace.string
            }
        }
    }
    

为什么这个方案可行?

  • 精准控制范围:只有明确遵循CaseIterableWithTitle的枚举才会获得titles属性,不会影响其他无关的Int枚举,解决了你之前担心的“不想给所有带Int原始值的枚举加功能”的问题。
  • 彻底消除重复:titles的核心逻辑只写一次,所有遵循协议的枚举自动复用,完全符合DRY原则。
  • 利用Swift特性:通过协议继承CaseIterable,直接使用allCases,不需要手动实现类似_allCases的额外属性,规避了你之前尝试协议时遇到的问题。

现在你可以直接调用CustomerTypes.titles或者EnquiryTypes.titles,效果和之前完全一样,但代码简洁了很多!

内容的提问来源于stack exchange,提问作者Sam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 17:22:46