【问题标题】:Closure containing control flow statement cannot be used with result builder 'CommandsBuilder'包含控制流语句的闭包不能与结果生成器“CommandsBuilder”一起使用
【发布时间】:2021-10-24 04:16:11
【问题描述】:

我制作了一个按钮样式来在我的应用中创建圆形神经拟态按钮,如下所示:

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)
    }
}

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

有没有什么方法可以根据赋予样式方向的 UnitPoint 来设置阴影和高光的偏移值,还是我必须为每种可能性制作一个按钮样式(这似乎是一个不可行的期望)?

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

【问题讨论】:

  • 您发布的代码中没有明显使用CommandsBuilder。编译器在哪一行标记错误?

标签: ios swift xcode swiftui viewbuilder


【解决方案1】:

Xcode 未能产生真正的错误,这就是他提到 CommandsBuilder 的原因。

一般遇到此类问题时,请尝试逐块注释代码以定位问题。

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


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

.mask(Circle().fill(LinearGradient(colors: [Color.black, Color.clear], startPoint: startPoint, endPoint: endPoint)))

应替换为:

.mask(Circle().fill(LinearGradient(gradient: Gradient(colors: [Color.black, Color.clear]), startPoint: startPoint, endPoint: endPoint)))

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

【讨论】:

  • 我很抱歉。我发布的代码块工作得很好。我为此使用了线性渐变的扩展,我将用它来更新我的问题。实际的问题是如何使用我在 makeBody 下方定义的函数在我的偏移量中设置 x:y: 的值?或者是否有根据我用开始和结束 UnitPoints 制作的渐变方向来设置这些变量?
  • @TheN3wbie .offset(x:, y:) 不能接受Int,只需将返回类型替换为CGFloat
  • 我尝试将调用封装在 CGFloat() 中,但那不起作用,您可以不将 Int 转换为 CGFloat 吗?
  • @TheN3wbie 如果您评论if .. { } else { } 并将if 的两个部分留在那里(只是为了构建它),Xcode 将能够告诉实际问题。
  • @TheN3wbie 包装应该可以工作,但是为什么不更改函数的返回类型呢?干净多了
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-01-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多