使用SWIFT5.2,我想创建一个函数来动态地更改形状
我的视野就像
import SwiftUI
struct CardView: View {
let suit : Suite
let rank : Rank
var body: some View {
getShape(suite: .heart)
.fill(Color.red) // .fill(suit.color)
.frame(width: 100, height: 100)
}
}我想要创建一个具有协议返回类型的形状的函数,在下面的示例中,我用我的自定义可能替换了泛型
func getShape(suite:Suite) -> Shape {
switch suite {
case .heart:
return Circle() // Heart()
case .diamond:
return Rectangle() // Diamond()
case .spade:
return Circle() // Heart()
case .club:
return Circle() // Club()
}
}我不能对某些类型使用不透明类型,因为我正在返回不同的类型,并且得到了一个编译错误。
Function declares an opaque return type, but the return statements in its body do not have matching underlying types 也不能像协议类型那样保留它,因为我得到了错误
Protocol 'Shape' can only be used as a generic constraint because it has Self or associated type requirements有什么办法能让我做到这一点吗?
发布于 2020-04-29 20:31:04
把@Asperi的回答和
struct AnyShape: Shape {
init<S: Shape>(_ wrapped: S) {
_path = { rect in
let path = wrapped.path(in: rect)
return path
}
}
func path(in rect: CGRect) -> Path {
return _path(rect)
}
private let _path: (CGRect) -> Path
}我可以把它改成
func getShape(suite:Suite) -> some Shape {
switch suite {
case .club:
return AnyShape(Club())
case .diamond:
return AnyShape(Diamond())
case .heart:
return AnyShape(Heart())
case .spade:
return AnyShape(Spade())
}
}
struct CardView: View {
let suit : Suite
let rank : Rank
var body: some View {
getShape(suite: suit)
.fill(Color.red)
.frame(width: 100, height: 100)
}发布于 2020-04-29 15:56:57
以下是可能的解决办法。
更新:用Xcode 13.4 / iOS 15.5测试
现在,海事组织最好放置所有这些模型并使用ViewBuilder,这样就不需要任何自定义包装/擦除了:
enum Suite {
case heart, diamond, spade, club
// Generate complete view and return opaque type
@ViewBuilder
var shape: some View { // << here !!
switch self {
case .heart:
Heart().fill(.red) // or make it self.color
case .diamond:
Diamond().fill(.red)
case .spade:
Spade().fill(.black)
case .club:
Club().fill(.black)
}
}
}
struct CardView: View {
let suit : Suite
let rank : Rank
var body: some View {
suit.shape // << as simple as !!
.frame(width: 100, height: 100)
}
}原件:用Xcode 11.4测试。
struct CardView: View {
let suit : Suite
let rank : Rank
var body: some View {
// pass all dependencies to generate view
getShape(suite: .heart, fill: suit.color)
.frame(width: 100, height: 100)
}
}
// Generate complete view and return opaque type
func getShape(suite: Suite, fill color: Color) -> some View {
switch suite {
case .heart:
return AnyView(Heart().fill(color))
case .diamond:
return AnyView(Diamond().fill(color))
case .spade:
return AnyView(Spade().fill(color))
case .club:
return AnyView(Club().fill(color))
}
}发布于 2021-08-12 10:20:43
我只想把这个留在这里
https://github.com/ohitsdaniel/ShapeBuilder
我最近开放了一个ShapeBuilder,它允许将计算的属性和函数标记为@ShapeBuilder或@InsettableShapeBuilder,通过利用结果生成器避免类型擦除。
这将允许您编写以下代码:
import ShapeBuilder
@ShapeBuilder func getShape(suite:Suite) -> some Shape {
switch suite {
case .heart:
Heart()
case .diamond:
Diamond()
case .spade:
Heart()
case .club:
Club()
}
}我还建议不要像前面的答复中所说的那样,向AnyView擦除。相反,可以使用@ViewBuilder标记getShape函数。这将函数体转换为视图生成器,就像SwiftUI视图主体属性一样,并且避免了类型擦除,这使得SwiftUI能够更容易地维护您的结构视图标识。
https://stackoverflow.com/questions/61503390
复制相似问题