错误:“某些视图”类型的值没有成员“笔划”

use*_*170 1 cs193p swift swiftui

我正在学习斯坦福大学的 CS193p 开发 iOS 应用程序在线课程。\n我使用的是 Xcode 11.5。(我没有更新,因为这是课程讲师(Paul Heagarty)正在使用的版本。)

\n

我正在尝试做作业3(设定游戏)。目前(为了避免重复代码)我正在尝试替换此片段:

\n
            VStack {\n                ForEach(0..<numberOfShapes) { index in\n                    if self.card.shape == .diamond {\n                        ZStack {\n                            Diamond().fill()\n                                .opacity(self.opacity)\n                            Diamond().stroke(lineWidth: self.shapeEdgeLineWidth)\n                        }\n                    }\n                    if self.card.shape == .squiggle {\n                        ZStack {\n                            Rectangle().fill()\n                            Rectangle().stroke(lineWidth: self.shapeEdgeLineWidth)\n                        }\n                    }\n                    if self.card.shape == .oval {\n                        ZStack {\n                            Ellipse().fill()\n                            Ellipse().stroke(lineWidth: self.shapeEdgeLineWidth)\n                        }\n                    }\n                }\n            }\n
Run Code Online (Sandbox Code Playgroud)\n

有了这个片段:

\n
            VStack {\n                ForEach(0..<numberOfShapes) { index in\n                    ZStack {\n                        shape(self.card.shape).opacity(self.opacity)\n                        shape(self.card.shape).stroke(lineWidth: 2.5) // ERROR here: Value of type \'some View\' has no member \'stroke\'\n                    }\n                }\n            }\n\n
Run Code Online (Sandbox Code Playgroud)\n

这个 @ViewBuilder 函数:

\n
@ViewBuilder\nfunc shape(_ shape: SetGameModel.Card.Shape) -> some View {\n    if shape == .diamond {\n        Diamond()\n    } else if shape == .squiggle {\n        Rectangle()\n    } else {\n        Ellipse()\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

这是完整的查看代码:

\n
import SwiftUI\n\nstruct SetGameView: View {\n    @ObservedObject var viewModel: SetGameViewModel\n    \n    var body: some View {\n        Grid(viewModel.cards) { card in\n                CardView(card: card).onTapGesture {\n                    self.viewModel.choose(card: card)\n                }\n                .padding(5)\n            }\n        .padding()\n        .foregroundColor(Color.orange)\n    }\n}\n\nstruct CardView: View {\n    var card: SetGameModel.Card\n\n    var numberOfShapes: Int {\n        switch card.numberOfShapes {\n        case .one:\n            return 1\n        case .two:\n            return 2\n        case .three:\n            return 3\n        }\n    }\n        \n    var opacity: Double {\n        switch card.shading {\n        case .open:\n            return 0.0\n        case .solid: // filled\n            return 1.0\n        case .striped: // you can use a semi-transparent color to represent the \xe2\x80\x9cstriped\xe2\x80\x9d shading.\n            return 0.33\n        }\n    }\n    \n    var color: Color {\n        switch card.color {\n        case .green:\n            return Color.green\n        case .purple:\n            return Color.purple\n        case .red:\n            return Color.red\n        }\n    }\n    \n    var body: some View {\n        ZStack {\n            RoundedRectangle(cornerRadius: cornerRadius).fill(Color.white)\n            RoundedRectangle(cornerRadius: cornerRadius)\n                .stroke(lineWidth: card.isChosen ? chosenCardEdgeLineWidth : normalCardEdgeLineWidth)\n                .foregroundColor(card.isChosen ? Color.red : Color.orange)\n            VStack {\n                ForEach(0..<numberOfShapes) { index in\n                    ZStack {\n                        shape(self.card.shape).opacity(self.opacity)\n                        shape(self.card.shape).stroke(lineWidth: 2.5) // ERROR here: Value of type \'some View\' has no member \'stroke\'\n                    }\n                }\n            }\n            .foregroundColor(self.color)\n            .padding()\n        }\n        .aspectRatio(cardAspectRatio, contentMode: .fit)\n    }\n    \n    // MARK: - Drawing Constants\n    let cornerRadius: CGFloat = 10.0\n    let chosenCardEdgeLineWidth: CGFloat = 6\n    let normalCardEdgeLineWidth: CGFloat = 3\n    let shapeEdgeLineWidth: CGFloat = 2.5\n    let cardAspectRatio: CGSize = CGSize(width: 2, height: 3) // 2/3 aspectRatio\n}\n\n@ViewBuilder\nfunc shape(_ shape: SetGameModel.Card.Shape) -> some View {\n    if shape == .diamond {\n        Diamond()\n    } else if shape == .squiggle {\n        Rectangle()\n    } else {\n        Ellipse()\n    }\n}\n\nstruct ContentView_Previews: PreviewProvider {\n    static var previews: some View {\n        SetGameView(viewModel: SetGameViewModel())\n    }\n}\n\n
Run Code Online (Sandbox Code Playgroud)\n

我有这个错误:

\n
Value of type \'some View\' has no member \'stroke\'\n
Run Code Online (Sandbox Code Playgroud)\n

我无法弄清楚,这是怎么回事?我该如何修复它?

\n

请尝试帮助我以某种方式修复它,我作为初学者会理解

\n

顺便说一句,Diamond() 是我的自定义 Shape(如 Rectangle())。\n如果您还需要 ViewModel、Model 或其他一些文件来帮助我修复它,请告诉我:-)

\n

Dáv*_*tor 5

stroke是在 上定义的Shape,而不是在上定义的,View并且您返回的是Shapes,而不仅仅是Views。您需要将返回类型更改shapesome Shape

遗憾的@ViewBuilder是,需要返回类型为some View,而不是some Shape,因此您需要删除该@ViewBuilder属性并确保您的函数Shape从每个分支返回相同的值。为了实现这一点,您可以实现一个类型擦除的ShapeAnyShape类似于AnyViewfor的调用View,并返回每个的类型擦除版本Shape

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 shape(_ shape: SetGameModel.Card.Shape) -> some Shape {
    if shape == .diamond {
        return AnyShape(Diamond())
    } else if shape == .squiggle {
        return AnyShape(Rectangle())
    } else {
        return AnyShape(Ellipse())
    }
}
Run Code Online (Sandbox Code Playgroud)