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

Swift中如何实现根据首个初始化参数动态调整后续入参的防错初始化?

解决方案

你可以通过两种Swift原生特性实现编译级别的参数校验,完全杜绝错误的参数搭配:

方案1:使用带关联值的枚举(推荐)

利用Swift枚举的关联值特性,直接将对齐参数和线条类型绑定,从类型层面强制参数对应关系:

修改后的代码

struct CustomLineShape: Shape {
    let kind: Kind
    let verticalAlignment: VerticalAlignment
    let horizontalAlignment: HorizontalAlignment
    
    enum Kind { 
        // 垂直线条绑定水平对齐参数
        case vertical(HorizontalAlignment)
        // 水平线条绑定垂直对齐参数
        case horizontal(VerticalAlignment) 
    }
    enum VerticalAlignment { case top, center, bottom }
    enum HorizontalAlignment { case leading, center, trailing }
    
    // 仅保留一个初始化方法,自动处理参数赋值
    init(kind: Kind) {
        self.kind = kind
        switch kind {
        case .vertical(let horizontalAlignment):
            self.horizontalAlignment = horizontalAlignment
            self.verticalAlignment = .center
        case .horizontal(let verticalAlignment):
            self.verticalAlignment = verticalAlignment
            self.horizontalAlignment = .center
        }
    }

    // 其余原有方法保持不变
    private func verticalFunction(rect: CGRect) -> CGFloat {
        switch verticalAlignment {
        case .top: return rect.minY
        case .center: return rect.midY
        case .bottom: return rect.maxY
        }
    }

    private func horizontalFunction(rect: CGRect) -> CGFloat {
        switch horizontalAlignment {
        case .leading: return rect.minX
        case .center: return rect.midX
        case .trailing: return rect.maxX
        }
    }

    func path(in rect: CGRect) -> Path {
        switch kind {
        case .horizontal:
            return Path { path in
                path.move(to: CGPoint(x: rect.minX, y: verticalFunction(rect: rect)))
                path.addLine(to: CGPoint(x: rect.maxX, y: verticalFunction(rect: rect)))
            }
        case .vertical:
            return Path { path in
                path.move(to: CGPoint(x: horizontalFunction(rect: rect), y: rect.minY))
                path.addLine(to: CGPoint(x: horizontalFunction(rect: rect), y: rect.maxY))
            }
        }
    }
}

调用方式

// 正确调用,编译器自动提示参数类型
CustomLineShape(kind: .vertical(.center))
CustomLineShape(kind: .horizontal(.top))

// 错误调用会直接编译报错,比如给.horizontal传HorizontalAlignment参数
// CustomLineShape(kind: .horizontal(.center)) 编译不通过

方案2:使用静态工厂方法(兼容原有Kind定义)

如果你不想修改原有Kind枚举的定义,可以通过暴露专用工厂方法、隐藏原有初始化方法的方式实现限制:

修改后的代码

struct CustomLineShape: Shape {
    let kind: Kind
    let verticalAlignment: VerticalAlignment
    let horizontalAlignment: HorizontalAlignment
    
    enum Kind { case vertical, horizontal }
    enum VerticalAlignment { case top, center, bottom }
    enum HorizontalAlignment { case leading, center, trailing }
    
    // 将原有初始化方法设为私有,禁止外部直接调用
    private init(kind: Kind, verticalAlignment: VerticalAlignment) {
        self.kind = kind
        self.verticalAlignment = verticalAlignment
        self.horizontalAlignment = .center
    }
    
    private init(kind: Kind, horizontalAlignment: HorizontalAlignment) {
        self.kind = kind
        self.horizontalAlignment = horizontalAlignment
        self.verticalAlignment = .center
    }
    
    // 暴露专用工厂方法
    static func vertical(alignment: HorizontalAlignment) -> CustomLineShape {
        .init(kind: .vertical, horizontalAlignment: alignment)
    }
    
    static func horizontal(alignment: VerticalAlignment) -> CustomLineShape {
        .init(kind: .horizontal, verticalAlignment: alignment)
    }

    // 其余原有方法保持不变
    private func verticalFunction(rect: CGRect) -> CGFloat {
        switch verticalAlignment {
        case .top: return rect.minY
        case .center: return rect.midY
        case .bottom: return rect.maxY
        }
    }

    private func horizontalFunction(rect: CGRect) -> CGFloat {
        switch horizontalAlignment {
        case .leading: return rect.minX
        case .center: return rect.midX
        case .trailing: return rect.maxX
        }
    }

    func path(in rect: CGRect) -> Path {
        switch kind {
        case .horizontal:
            return Path { path in
                path.move(to: CGPoint(x: rect.minX, y: verticalFunction(rect: rect)))
                path.addLine(to: CGPoint(x: rect.maxX, y: verticalFunction(rect: rect)))
            }
        case .vertical:
            return Path { path in
                path.move(to: CGPoint(x: horizontalFunction(rect: rect), y: rect.minY))
                path.addLine(to: CGPoint(x: horizontalFunction(rect: rect), y: rect.maxY))
            }
        }
    }
}

调用方式

// 正确调用
CustomLineShape.vertical(alignment: .center)
CustomLineShape.horizontal(alignment: .top)

// 原有错误调用方式会直接编译报错,因为初始化方法已被私有

效果说明

两种方案都能实现编译级别的参数校验,你提到的CustomLineShape(kind: .horizontal, horizontalAlignment: .center)这类逻辑错误的调用会直接被编译器拦截,完全符合你的防错需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 02:15:01