在 SwiftUI 中,我有两个包装 Shape 的结构,一个有效,一个无效,但我看不出两者有任何功能差异

In SwiftUI, I have two structs that wrap a Shape, one works, one does not, yet I do not see any functional difference in the two

我包装了两个 Shape 结构。一个工作,另一个编译并运行 - 但总是在屏幕上呈现空白区域。然而,我没有看到这两个结构在功能上有任何关键区别……AnyShape_AlwaysBlank 有什么不同之处使它无法将形状渲染为视图?

import SwiftUI
import PlaygroundSupport

struct AnyShape_Working: Shape {
    
    private let someShapePath: (CGRect) -> Path
    
    // required to conform to Shape 
    public func path(in rect: CGRect) -> Path {
        someShapePath(rect)
    }
    
    init<S: Shape>(_ someShape: S) {
        someShapePath = { rect in
            someShape.path(in: rect)
        }
    }
}

struct AnyShape_AlwaysBlank: Shape {
    
    private let someShapePath: Path 
    
    // required to conform to Shape
    public func path(in rect: CGRect) -> Path {
        someShapePath
    }
    
    init<S: Shape>(_ someShape: S) {
        let rect = CGRect()
        someShapePath = someShape.path(in: rect)
    }
}

struct ContentView: View {
    
    var body: some View {
        VStack {
            Text("Circle will appear below")
            AnyShape_Working( Circle() )
            Text("Blank area will appear below")
            AnyShape_AlwaysBlank( Circle() )
        }
    }
}

PlaygroundPage.current.setLiveView( ContentView() )

在第一种情况下,当调用 path(in rect: CGRect) -> Path 时,它实际上使用传递给它的 rect 来创建 Path.

在第二种情况下,您 pre-created Path 使用 CGRect(),它是一个空的 CGRect,所以路径 returned 是一个适合空 rect。然后当 path(in rect: CGRect) -> Path 被调用时,您将忽略 rect 参数,而只是 returning pre-created Path.


另一种方法是使结构通用,然后存储 Shape:

struct AnyShape<S: Shape>: Shape {
    
    private let someShape: S
    
    // required to conform to Shape
    public func path(in rect: CGRect) -> Path {
        someShape.path(in: rect)
    }
    
    init(_ someShape: S) {
        self.someShape = someShape
    }
}

注意:如果您想使用 AnyShape 将所有 Shape 统一为一个类型,这个 Generic 版本不会那样做,因为它 return 每个输入形状都有不同的类型:AnyShape<Circle> 代表 CircleAnyShape<Rectangle> 代表 Rectangle,等。在这种情况下,我会坚持使用闭包捕获 ShapeAnyShape 或者如果您希望 func 成为 @ViewBuilder return 函数中的多个 Shape 类型。