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
相关产品推荐
相关产品推荐

