首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在SwiftUI中动态获取视图形状

在SwiftUI中动态获取视图形状
EN

Stack Overflow用户
提问于 2020-04-29 13:49:54
回答 3查看 2.5K关注 0票数 7

使用SWIFT5.2,我想创建一个函数来动态地更改形状

我的视野就像

代码语言:javascript
复制
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)
     }
}

我想要创建一个具有协议返回类型的形状的函数,在下面的示例中,我用我的自定义可能替换了泛型

代码语言:javascript
复制
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()

    }
}

我不能对某些类型使用不透明类型,因为我正在返回不同的类型,并且得到了一个编译错误。

代码语言:javascript
复制
Function declares an opaque return type, but the return statements in its body do not have matching underlying types 

也不能像协议类型那样保留它,因为我得到了错误

代码语言:javascript
复制
Protocol 'Shape' can only be used as a generic constraint because it has Self or associated type requirements

有什么办法能让我做到这一点吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2020-04-29 20:31:04

把@Asperi的回答和

代码语言:javascript
复制
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
}

我可以把它改成

代码语言:javascript
复制
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)
 }
票数 15
EN

Stack Overflow用户

发布于 2020-04-29 15:56:57

以下是可能的解决办法。

更新:用Xcode 13.4 / iOS 15.5测试

现在,海事组织最好放置所有这些模型并使用ViewBuilder,这样就不需要任何自定义包装/擦除了:

代码语言:javascript
复制
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测试。

代码语言:javascript
复制
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))
   }
}
票数 5
EN

Stack Overflow用户

发布于 2021-08-12 10:20:43

我只想把这个留在这里

https://github.com/ohitsdaniel/ShapeBuilder

我最近开放了一个ShapeBuilder,它允许将计算的属性和函数标记为@ShapeBuilder@InsettableShapeBuilder,通过利用结果生成器避免类型擦除。

这将允许您编写以下代码:

代码语言:javascript
复制
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能够更容易地维护您的结构视图标识。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61503390

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档