所有 SwiftUI 形状的通用类型

问题描述 投票:0回答:1

我为 SwiftUI 编写了一段代码,根据

Shape
参数提供特定的
Enum
。不幸的是,一个看起来很自然的
switch
命令抱怨
Rectangle()
Circle()
Diamond()
(我自己的
Shape
)的类型全部不匹配。

我怎样才能让 Xcode 相信所有这些都是

Shape
并且在进一步的代码中都完全符合 SwiftUI 修饰符?

演示问题的代码片段:

import SwiftUI

enum MaskShapes {
    case rectangle, diamond, circle
}

struct ContentView: View {
    var body: some View {
        let shape = MaskShapes.diamond
        let mask = switch shape {
        case .rectangle: Rectangle() // Error: Branches have mismatching types 'Rectangle' and 'Circle'
        case .diamond: Diamond() // Error: Branches have mismatching types 'ContentView.Diamond' and 'Circle'
        case .circle: Circle()
        }
        
        Spacer()
        VStack {
            Image(systemName: "globe")
                .imageScale(.large)
            Text("Hello, world!")
        }
        .frame(width: 300, height: 200)
        .background(mask.foregroundColor(.red))
        Spacer()
    }
    
    struct Diamond: Shape {
        func path(in rect: CGRect) -> Path {
            var p = Path()
            p.move(to: CGPoint(x: rect.midX, y: 0))
            p.addLine(to: CGPoint(x: 0, y: rect.midY))
            p.addLine(to: CGPoint(x: rect.midX, y: rect.maxY))
            p.addLine(to: CGPoint(x: rect.maxX, y: rect.midY))
            p.closeSubpath()
            return p
        }
    }
}

#Preview {
    ContentView()
}

预期效果 - 分别使用每个形状实现:

swift xcode swiftui protocols shapes
1个回答
0
投票

如果 SwiftUI 支持

ShapeBuilder
属性,那就太好了。也许你可以自己写,但我不认为这会很容易。因此,这里有两种可能的解决方法:

1。创建

ViewBuilder
函数,创建指定的
Shape

我认为它还需要使用

if-else
而不是
switch

@ViewBuilder
func mask(shape: MaskShapes) -> some View {
    if shape == .rectangle {
        Rectangle()
    } else if shape == .diamond {
        Diamond()
    } else {
        Circle()
    }
}

var body: some View {
    let shape = MaskShapes.diamond

    Spacer()
    VStack {
        Image(systemName: "globe")
            .imageScale(.large)
        Text("Hello, world!")
    }
    .frame(width: 300, height: 200)
    .background(mask(shape: shape).foregroundColor(.red))
    Spacer()
}

2。将

Shape
提供给通用函数

此方法保留了

Shape
类型,因此如果您想使用特定于形状的修改器,那么您可以:

@ViewBuilder
func bodyWithShapedBackground<S: Shape>(shape: S) -> some View {
    Spacer()
    VStack {
        Image(systemName: "globe")
            .imageScale(.large)
        Text("Hello, world!")
    }
    .frame(width: 300, height: 200)
    .background(shape.foregroundColor(.red))
    Spacer()
}

var body: some View {
    let shape = MaskShapes.diamond
    if shape == .rectangle {
        bodyWithShapedBackground(shape: Rectangle())
    } else if shape == .diamond {
        bodyWithShapedBackground(shape: Diamond())
    } else {
        bodyWithShapedBackground(shape: Circle())
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.