无法在 SwiftUI 'Text' 中推断通用类型 'S' 在 CS193p 项目中,在 Xcode 中

Can't Infer Generic Type 'S' in SwiftUI 'Text' in CS193p project, in Xcode

背景

我正在关注 Stanfords 的 CS193p iOS 开发在线课程。我使用 Xcode 11.3 和 Swift 5.1.2.

问题

第五讲ViewBuilder + Shape + ViewModifier 结束的时候,我遇到了一个错误,就是Swift编译器报错'Generic parameter 'S' could not be inferred'。 Snapshot: IDE complains about it

代码片段

EmojiMemoryGameView.swift

中的代码
import SwiftUI

struct EmojiMemoryGameView: View {
    @ObservedObject var viewModel: EmojiMemoryGame
    var body: some View {
        Grid(viewModel.cards) { card in
            CardView(card: card).onTapGesture(perform: {
                self.viewModel.choose(card: card)
            })
            .padding(5)
        }
            .padding()
            .foregroundColor(Color.orange)
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        let game = EmojiMemoryGame()
        game.choose(card: game.cards[0])
        return EmojiMemoryGameView(viewModel: game)
    }
}


struct CardView: View {
    var card: MemoryGame<String>.Card
    
    var body: some View {
        GeometryReader { geometry in
            self.body(for: geometry.size)
        }
    }
    
    @ViewBuilder
    private func body(for size: CGSize) -> some View {
        if card.isFaceUp || !card.isMatched {
            ZStack {
                Pie(startAngle: Angle.degrees(-90),
                    endAngle: Angle.degrees(-10),
                    clockwise: true)
                    .padding(5)
                    .opacity(0.3)
                Text(card.content)
                    .font(Font.system(size: fontSize(for: size)))
                }.cardify(isFaceUp: card.isFaceUp)
            //.modifier(Cardify(isFaceUp: card.isFaceUp))
        }
    }
    
    
    private func fontSize(for size: CGSize) -> CGFloat {
        return min(size.width, size.height) * fontScaleFactor
    }
    // MARK: - Drawing Constants
    
    private let fontScaleFactor: CGFloat = 0.75
}

}

MemoryGame.swift

中的代码
import Foundation

struct MemoryGame<CardContent> where CardContent: Equatable { // costraints and gains
    private(set) var cards: Array<Card>
    private var indexOfTheOneAndOnlyFaceUpCard: Int? {
        get {
            cards.indices.filter { cards[[=14=]].isFaceUp }.only
        }
        set {
            for index in cards.indices {
                // newValue is a var only appears in set method
                cards[index].isFaceUp = index == newValue
            }
        }
    }
    
    init(numberOfPairsOfCards: Int, cardContentFactory: (Int) -> CardContent) {
        cards = Array<Card>()
        let maxIndex = 2 * numberOfPairsOfCards - 1
        var pairIndices = [Int]()
        for i in 0...maxIndex {
            let randomNumber = Double.random(in: 0...1)
            if randomNumber >= 0.5 {
                pairIndices.insert(i/2, at: 0)
            } else {
                pairIndices.append(i/2)
            }
        }
        for i in 0...maxIndex {
            let pairIndex = pairIndices[i]
            let content = cardContentFactory(pairIndex)
            cards.append(Card(id: i, content: content))
        }
    }
                    
    mutating func choose(card: Card) {
        print("card chosen: \(card)")
        if let chosenIndex = cards.firstIndex(matching: card), !cards[chosenIndex].isFaceUp, !cards[chosenIndex].isMatched {
            // comma here is like a sequential "AND"
            if let potentialMatchIndex = indexOfTheOneAndOnlyFaceUpCard {
                if cards[chosenIndex].content ==  cards[potentialMatchIndex].content {
                    cards[chosenIndex].isMatched = true
                    cards[potentialMatchIndex].isMatched = true
                }
            } else {
                indexOfTheOneAndOnlyFaceUpCard = chosenIndex
            }
            self.cards[chosenIndex].isFaceUp = true
        }
    }
    
    struct Card: Identifiable {
        /* Member variable 'id' is essential for the Identifiable protocol */
        var id: Int
        
        var isFaceUp: Bool = false
        var isMatched: Bool = false
        var content: CardContent
    }
}

但是,当我按住 alt 并单击变量时,它清楚地显示类型是 String。 Snapshot: Type Declaration

我当前的项目代码也可以在 Github

为什么会出现错误?我该如何解决?

感谢您的帮助!

在你的struct CardView: View中,你有

if card.isFaceUp || !card.isMatched {
            ZStack {
                Pie(startAngle: Angle.degrees(-90),
                    endAngle: Angle.degrees(-10),
                    clockwise: true)
                    .padding(5)
                    .opacity(0.3)
                Text(card.content)
                    .font(Font.system(size: fontSize(for: size)))
                }.cardify(isFaceUp: card.isFaceUp)
            //.modifier(Cardify(isFaceUp: card.isFaceUp))
        }

ZStack 之前添加一个 return,这应该可以解决您的问题。

if card.isFaceUp || !card.isMatched {
                return ZStack {
                    Pie(startAngle: Angle.degrees(-90),
                        endAngle: Angle.degrees(-10),
                        clockwise: true)
                        .padding(5)
                        .opacity(0.3)
                    Text(card.content)
                        .font(Font.system(size: fontSize(for: size)))
                    }.cardify(isFaceUp: card.isFaceUp)
                //.modifier(Cardify(isFaceUp: card.isFaceUp))
            }