I am looking to call two variables but the method I am trying to implement does not work.
Unfortunately, Xcode says Extra argument in call.
I am a newbie, can someone help me to understand what is going wrong ?
Thank you !!
struct Card {
let content : [String]
let names:[String]
static let allCards:[Card] =
[
Card(content: ["content1","content2"], names: ["name1","name2"]),
Card(content: ["content3","content4"], names: ["name3","name4"])
]
}
struct Play {
let cards = Card.allCards.shuffled()
var currentCardIndex = 0
var currentCard:Card {
cards[currentCardIndex]
}
}
class GameViewModel {
@Published var play = Play()
var cardContent:[String] {
play.currentCard.content
}
var cardnames:[String] {
play.currentCard.names
}
}
struct CardView:View {
let contentString:String
let nameString:String
var body: some View{
HStack{
Text(contentString)
Text(nameString)
}
}
}
struct ContentView: View {
var viewModel = GameViewModel()
var body: some View {
HStack{
/ Warning: Extra argument in call
ForEach(viewModel.cardContent, viewModel.cardnames,id:\.self, content:{ card in
CardView(contentString: card, nameString: card).frame(minWidth: 135, idealWidth: 250, maxWidth: 135, minHeight: 135, idealHeight: 250, maxHeight: 135, alignment: .center).aspectRatio(2/2, contentMode:.fit)
})
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
CodePudding user response:
The root cause:
In ForEach(viewModel.cardContent, viewModel.cardnames
either viewModel.cardContent
or viewModel.cardnames
is an extra argument, as ForEach
can iterate only one array, and you are passing 2 arrays.
The simplest fix: pass only one array (viewModel.play.cards
) in
ForEach(viewModel.play.cards, id:\.self, content: { card in
CardView(contentString: card.content, nameString: card.names).frame(minWidth: 135, idealWidth: 250, maxWidth: 135, minHeight: 135, idealHeight: 250, maxHeight: 135, alignment: .center).aspectRatio(2/2, contentMode:.fit)
})
The example above still may not compile because of CardView(contentString: card
constructor, but that's another problem :)
CodePudding user response:
Yes, it throws an error because you are passing more than the available arguments to constructor of ForEach
You can see the below available constructor of ForEach
, then you come to know which argument you are passing it as extra to the constructor
init(_ data: Data, @AccessibilityRotorContentBuilder content: @escaping (Data.Element) -> Content)
init(_ data: Data, id: KeyPath<Data.Element, ID>, @AccessibilityRotorContentBuilder content: @escaping (Data.Element) -> Content)
init(_ data: Data, @ViewBuilder content: @escaping (Data.Element) -> Content)
init(_ data: Data, id: KeyPath<Data.Element, ID>, @ViewBuilder content: @escaping (Data.Element) -> Content)
init<C>(_ data: Binding<C>, @ViewBuilder content: @escaping (Binding<C.Element>) -> Content) where Data == LazyMapSequence<C.Indices, (C.Index, ID)>, ID == C.Element.ID, C : MutableCollection, C : RandomAccessCollection, C.Element : Identifiable, C.Index : Hashable
init<C>(_ data: Binding<C>, id: KeyPath<C.Element, ID>, @ViewBuilder content: @escaping (Binding<C.Element>) -> Content) where Data == LazyMapSequence<C.Indices, (C.Index, ID)>, C : MutableCollection, C : RandomAccessCollection, C.Index : Hashable
And in your code
//viewModel.cardnames is the extra argument you are passing to ForEach
ForEach(viewModel.cardContent, viewModel.cardnames,id:\.self, content:{ card in
CardView(contentString: card, nameString: card).frame(minWidth: 135, idealWidth: 250, maxWidth: 135, minHeight: 135, idealHeight: 250, maxHeight: 135, alignment: .center).aspectRatio(2/2, contentMode:.fit)
})