Получить форму для просмотра динамически в SwiftUI - PullRequest
0 голосов
/ 29 апреля 2020

Используя Swift 5.2, я хотел бы создать функцию для динамического изменения Shape

У меня есть вид как

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)
     }
}

Я хотел бы создать Функция с типом возврата протокола Shape, я заменил свои пользовательские shaps на generi c в примере ниже

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()

    }
}

Я не могу использовать непрозрачный тип с some , потому что я возвращаю различных типов, и я получаю ошибку компиляции

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

Есть ли способ, которым я могу добиться этого элегантно?

Ответы [ 2 ]

2 голосов
/ 29 апреля 2020

Здесь возможное решение. Протестировано с 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))
   }
}
0 голосов
/ 29 апреля 2020

Объединив ответ @ Аспери с

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)
 }
...