在 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>
代表 Circle
,AnyShape<Rectangle>
代表 Rectangle
,等。在这种情况下,我会坚持使用闭包捕获 Shape
的 AnyShape
或者如果您希望 func
成为 @ViewBuilder
return 函数中的多个 Shape
类型。
我包装了两个 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>
代表 Circle
,AnyShape<Rectangle>
代表 Rectangle
,等。在这种情况下,我会坚持使用闭包捕获 Shape
的 AnyShape
或者如果您希望 func
成为 @ViewBuilder
return 函数中的多个 Shape
类型。