包含控制流语句的闭包不能与结果生成器“CommandsBuilder”一起使用

the*_*ooL 5 xcode ios swift swiftui viewbuilder

我制作了一个按钮样式来在我的应用程序中创建圆形同形按钮,如下所示:

struct NeumorphicCircleButtonStyle: ButtonStyle {
    var startPoint: UnitPoint
    var endPoint: UnitPoint
    var padding: CGFloat?
    var bgColor: Color?
    var bgColorOffset: Color?
    
    func makeBody(configuration: Configuration) -> some View {
        
        configuration.label
            .padding(padding ?? 30)
            .contentShape(Circle())
            .background(
                Group{
                    if configuration.isPressed {
                        Circle()
                            .fill(bgColor ?? Color.backgroundColor)
                            .overlay(
                                Circle()
                                    .stroke(Color.black.opacity(0.7), lineWidth: 4)
                                    .blur(radius: 4)
                                    .offset(x: 2, y: 2)
                                    .mask(Circle().fill(LinearGradient(colors: [Color.black, Color.clear], startPoint: startPoint, endPoint: endPoint)))
                            )
                            .overlay(
                                Circle()
                                    .stroke(bgColorOffset ?? Color.backgroundColorOffset, lineWidth: 8)
                                    .blur(radius: 4)
                                    .offset(x: -2, y: -2)
                                    .mask(Circle().fill(LinearGradient(colors: [Color.clear, Color.black], startPoint: startPoint, endPoint: endPoint)))
                            )
                    } else {
                        Circle()
                            .fill(bgColor ?? Color.backgroundColor)
                            .shadow(color: Color.black.opacity(0.25), radius: 10, x: 10, y: 10)
                            .shadow(color: bgColorOffset ?? Color.backgroundColorOffset.opacity(0.7), radius: 10, x: -5, y: -5)
                    }
                }
            )
    }
    
    // TODO: this will change the x y on the first set and need to make for other x y sets for direction, but can't find a good place for the logic, can't call it from in the makebody anywhere
    func getXoffetInnerShadow() -> Int {
        switch endPoint {
        case .bottomTrailing:
            return 2
        case .bottomLeading:
            return -2
        case .topTrailing:
            return 2
        case .topLeading:
            return -2
        case .leading:
            return -2
        case .trailing:
            return 2
        default:
            return 0
        }
    }
    
    func getYoffsetInnerShadow() -> Int {
        switch endPoint {
        case .bottomTrailing:
            return 2
        case .bottomLeading:
            return 2
        case .bottom:
            return 2
        case .topTrailing:
            return -2
        case .topLeading:
            return -2
        case .top:
            return -2
        default:
            return 0
        }
    }
    
    func getXoffetInnerHighlight() -> Int {
        switch endPoint {
        case .bottomTrailing:
            return -2
        case .bottomLeading:
            return 2
        case .topTrailing:
            return -2
        case .topLeading:
            return -2
        case .leading:
            return 2
        case .trailing:
            return -2
        default:
            return 0
        }
    }
    
    func getYoffsetInnerHighlight() -> Int {
        switch endPoint {
        case .bottomTrailing:
            return -2
        case .bottomLeading:
            return -2
        case .bottom:
            return -2
        case .topTrailing:
            return 2
        case .topLeading:
            return 2
        case .top:
            return 2
        default:
            return 0
        }
    }
    
    func getXoffsetShadow() -> Int {
        switch endPoint {
        case .bottomTrailing:
            return 10
        case .bottomLeading:
            return -10
        case .topTrailing:
            return 10
        case .topLeading:
            return -10
        case .leading:
            return -10
        case .trailing:
            return 10
        default:
            return 0
        }
    }
    
    func getYoffsetShadow() -> Int {
        switch endPoint {
        case .bottomTrailing:
            return 10
        case .bottomLeading:
            return 10
        case .bottom:
            return 10
        case .topTrailing:
            return -10
        case .topLeading:
            return -10
        case .top:
            return -10
        default:
            return 0
        }
    }
    
    func getXoffsetHighlight() -> Int {
        switch endPoint {
        case .bottomTrailing:
            return -10
        case .bottomLeading:
            return 10
        case .topTrailing:
            return -10
        case .topLeading:
            return 10
        case .leading:
            return 10
        case .trailing:
            return -10
        default:
            return 0
        }
    }
    
    func getYoffsetHighlight() -> Int {
        switch endPoint {
        case .bottomTrailing:
            return -10
        case .bottomLeading:
            return -10
        case .bottom:
            return -10
        case .topTrailing:
            return 10
        case .topLeading:
            return 10
        case .top:
            return 10
        default:
            return 0
        }
    }
}


    // this is how I init my gradient if you want a working example
extension LinearGradient {
    init(_ colors: Color..., startPoint: UnitPoint, endPoint: UnitPoint) {
        self.init(gradient: Gradient(colors: colors), startPoint: startPoint, endPoint: endPoint)
    }
}
Run Code Online (Sandbox Code Playgroud)

我试图根据传递给样式的渐变端点来更改两个阴影和高光的偏移,以便内部和外部发光和阴影始终位于按钮的适当一侧。但是,尝试向偏移值添加 switch case 或函数调用以返回适当的值会引发Closure containing control flow statement cannot be used with result builder 'CommandsBuilder'编译时异常。

有没有什么方法可以根据给定方向样式的 UnitPoint 设置阴影和高光的偏移值,或者我是否必须为每种可能性创建一个按钮样式(这似乎是一个不可行的期望)?

非常感谢任何和所有的帮助或建议!

Phi*_*hov 7

Xcode 未能产生真正的错误,这就是他所说的CommandsBuilder.

通常,当您遇到此类问题时,请尝试逐块注释代码以定位问题。

在这种情况下,如果您注释if .. { } else { }并保留if其中的两个部分(只是为了构建它),Xcode 将能够告诉实际问题


在这种情况下LinearGradient没有init(colors: ...,所以两行

.mask(Circle().fill(LinearGradient(colors: [Color.black, Color.clear], startPoint: startPoint, endPoint: endPoint)))
Run Code Online (Sandbox Code Playgroud)

应替换为:

.mask(Circle().fill(LinearGradient(gradient: Gradient(colors: [Color.black, Color.clear]), startPoint: startPoint, endPoint: endPoint)))
Run Code Online (Sandbox Code Playgroud)

如果您想使用下面定义的函数,例如修饰符getXoffetInnerShadow的参数.offset,您应该将返回类型替换为CGFloat,因为这是唯一.offset接受的类型。