如何对不同的形状使用相同的修饰符集
Posted
技术标签:
【中文标题】如何对不同的形状使用相同的修饰符集【英文标题】:How to use same set of modifiers for various shapes 【发布时间】:2020-06-26 20:10:03 【问题描述】:作为我学习 SwiftUI 项目的一部分,我做了一些形状旋转,下面有代码。我想知道如何避免每个形状使用相同的三行修饰符。
func getShape(shape: Int, i: Int) -> AnyView
switch shape
case 0:
return AnyView(Rectangle()
.stroke(colors[Int(shapeColor)])
.frame(width: CGFloat(shapeWidth), height: CGFloat(shapeHeight))
.rotationEffect(Angle(degrees: Double(i) * Double(angleStep))))
case 1:
return AnyView(Capsule()
.stroke(colors[Int(shapeColor)])
.frame(width: CGFloat(shapeWidth), height: CGFloat(shapeHeight))
.rotationEffect(Angle(degrees: Double(i) * Double(angleStep))))
case 2:
return AnyView(Ellipse()
.stroke(colors[Int(shapeColor)])
.frame(width: CGFloat(shapeWidth), height: CGFloat(shapeHeight))
.rotationEffect(Angle(degrees: Double(i) * Double(angleStep))))
default:
return AnyView(Rectangle()
.stroke(colors[Int(shapeColor)])
.frame(width: CGFloat(shapeWidth), height: CGFloat(shapeHeight))
.rotationEffect(Angle(degrees: Double(i) * Double(angleStep))))
【问题讨论】:
【参考方案1】:使用助手AnyShape
类型橡皮擦
struct AnyShape: Shape
private let builder: (CGRect) -> Path
init<S: Shape>(_ shape: S)
builder = rect in
let path = shape.path(in: rect)
return path
func path(in rect: CGRect) -> Path
return builder(rect)
你的函数可以写成
func getShape(shape: Int, i: Int) -> some View
let selectedShape: AnyShape =
switch shape
case 0:
return AnyShape(Rectangle())
case 1:
return AnyShape(Capsule())
case 2:
return AnyShape(Ellipse())
default:
return AnyShape(Rectangle())
()
return selectedShape
.stroke(colors[Int(shapeColor)])
.frame(width: CGFloat(shapeWidth), height: CGFloat(shapeHeight))
.rotationEffect(Angle(degrees: Double(i) * Double(angleStep))))
【讨论】:
【参考方案2】:您可以使用辅助函数和扩展来抽象出一些重复。
在下面的简化示例中,我使用@ViewBuilder
来清理我们返回的代码。无需使用AnyView
,它使代码更易于阅读。
如果我们能返回 some Shape
那就太好了,但这是
目前不可能并导致错误。这就是为什么中风
必须为 getShape
中的每个 Shape
重复值
函数,否则我们可以在Shape
上进行扩展
而不是View
。
我在View
上创建了一个扩展,它允许我们将修饰符组合到一个函数中,使其更具可读性和更易于使用。老实说,这部分是可选的,您可以使用两个修饰符 frame
和 rotationEffect
。
@ViewBuilder getShape(shape:index:)
返回您选择的形状及其选择的颜色,然后由函数 createShape(shape:index:)
使用,您可以在其中添加我们在 View
上作为扩展创建的自定义修饰符。
最后我们创建了我们的形状
这应该给你一个起点。
struct ShapeView: View
@ViewBuilder // 1
func getShape(shape: Int, i: Int) -> some View
switch shape
case 0:
Rectangle().stroke(Color.red)
case 1:
Capsule().stroke(Color.red)
case 2:
Ellipse().stroke(Color.red)
default:
Rectangle().stroke(Color.red)
func createShape(shape: Int, index: Int) -> some View // 3
getShape(shape: shape, i: index)
.myModifier(width: 200, height: 100, index: index, angleStep: 30)
var body: some View
createShape(shape: 2, index: 1) // 4
// 2
extension View
func myModifier(width: CGFloat, height: CGFloat, index: Int, angleStep: Double) -> some View
self
.frame(width: width, height: height)
.rotationEffect(Angle(degrees: Double(index) * Double(angleStep)))
struct ShapeView_Previews: PreviewProvider
static var previews: some View
ShapeView()
很遗憾,我们不能从@ViewBuilder
返回some Shape
,或者如果存在@ShapeBuilder
,因为这意味着我们不必将笔划单独添加到每个形状,作为@ 987654338@不能中风。
【讨论】:
【参考方案3】:嵌套函数可以帮助清理代码:
func getShape(shape: Int, i: Int) -> some View
func adjustedView<S: Shape>(shape: S) -> some View
shape
.stroke(colors[Int(shapeColor)])
.frame(width: CGFloat(shapeWidth), height: CGFloat(shapeHeight))
.rotationEffect(Angle(degrees: Double(i) * Double(angleStep))))
return Group
switch shape
case 0:
adjustedView(shape: Rectangle())
case 1:
adjustedView(shape: Capsule())
case 2:
adjustedView(shape: Ellipse())
default:
adjustedView(shape: Rectangle())
另一种选择是使用便利功能扩展Shape
。即
extension Shape
func adjust(shapeWidth: Double, shapeHeight: Double, angle: Angle) -> some View
self.stroke()
//.stroke(colors[Int(shapeColor)]) // for brevity
.frame(width: CGFloat(shapeWidth), height: CGFloat(shapeHeight))
.rotationEffect(angle)
它稍微简化了代码。也不需要擦除类型。
func getShape(shape: Int, i: Int) -> some View
Group
switch shape
case 0:
Rectangle().adjust(shapeWidth: shapeWidth, shapeHeight: shapeHeight, angle: Angle(degrees: Double(i) * Double(angleStep))))
case 1:
Capsule().adjust(shapeWidth: shapeWidth, shapeHeight: shapeHeight, angle: Angle(degrees: Double(i) * Double(angleStep))))
case 2:
Ellipse().adjust(shapeWidth: shapeWidth, shapeHeight: shapeHeight, angle: Angle(degrees: Double(i) * Double(angleStep))))
default:
Rectangle().adjust(shapeWidth: shapeWidth, shapeHeight: shapeHeight, angle: Angle(degrees: Double(i) * Double(angleStep))))
【讨论】:
以上是关于如何对不同的形状使用相同的修饰符集的主要内容,如果未能解决你的问题,请参考以下文章