101

I seem to be getting a random "Extra argument in call." error while coding a tip calculator. Here is my SwiftUI File:

import SwiftUI internal enum ReceiptRowType { case subtotal case tax case total case tip case grandTotal } struct TipView: View { @ObservedObject internal var adBannerView: BannerAdView = BannerAdView() @ObservedObject internal var receiptViewModel: ReceiptViewModel private let percentageFormatter: NumberFormatter = { let f = NumberFormatter() f.numberStyle = .percent return f }() var body: some View { ZStack { Color.white .scaledToFit() VStack { if adBannerView.adHasLoaded { adBannerView .frame(maxHeight: adBannerView.adHeight) .animation(.easeInOut(duration: 2.0)) } BorderView() Text(ARCHLocalizedStrings.receipt) .foregroundColor(Color.gray) BorderView() HStack { Spacer() Button(action: { self.receiptViewModel.addNewReceiptItem() }) { Text(ARCHLocalizedStrings.buttonTitleAddItem) } } BorderView() ScrollView { ForEach(receiptViewModel.receiptItems) { receiptItem in ItemView(receiptItem: receiptItem) if receiptItem != self.receiptViewModel.receiptItems.last { Divider() } } } BorderView() BottomOfReceiptRow(receiptViewModel: receiptViewModel, type: ReceiptRowType.subtotal, title: ARCHLocalizedStrings.subtotal) BottomOfReceiptRow(receiptViewModel: receiptViewModel, type: ReceiptRowType.tax, title: ARCHLocalizedStrings.tax) } .padding(.horizontal, ARCHSwiftUILayoutConstants.defaultPaddingAndSpacing) } } } struct BorderView: View { var body: some View { Text("================================") .lineLimit(1) .foregroundColor(Color.gray) .minimumScaleFactor(0.5) } } struct ItemView: View { @ObservedObject var receiptItem: ReceiptItemViewModel var body: some View { HStack { TextField(receiptItem.name, text: $receiptItem.name) .textFieldStyle(RoundedBorderTextFieldStyle()) .foregroundColor(Color.gray) .multilineTextAlignment(TextAlignment.leading) TextField("Price", value: $receiptItem.price, formatter: ARCHUtilities.currencyFormatter) .textFieldStyle(RoundedBorderTextFieldStyle()) .foregroundColor(Color.gray) .multilineTextAlignment(TextAlignment.trailing) .minimumScaleFactor(0.5) .frame(width: ARCHSwiftUILayoutConstants.widthForCurrency) } } } struct BottomOfReceiptRow: View { @ObservedObject internal var receiptViewModel: ReceiptViewModel internal var type: ReceiptRowType internal var title: String var body: some View { HStack { Spacer() Text(title) .foregroundColor(Color.gray) if type == ReceiptRowType.subtotal { Text("\(receiptViewModel.subtotal)") .foregroundColor(Color.gray) .frame(width: ARCHSwiftUILayoutConstants.widthForCurrency) } else if type == ReceiptRowType.tax { Text("\(receiptViewModel.taxRate)") .foregroundColor(Color.gray) .frame(width: ARCHSwiftUILayoutConstants.widthForCurrency) } else if type == ReceiptRowType.total { Text("\(receiptViewModel.total)") .foregroundColor(Color.gray) .frame(width: ARCHSwiftUILayoutConstants.widthForCurrency) } else if type == ReceiptRowType.tip { } else if type == ReceiptRowType.grandTotal { Text("\(receiptViewModel.grandTotal)") .foregroundColor(Color.gray) .frame(width: ARCHSwiftUILayoutConstants.widthForCurrency) } } } } struct TipView_Previews: PreviewProvider { static var previews: some View { TipView(receiptViewModel: ReceiptViewModel()) } } 

However, if I add another view on the TipView body (any view), I seem to get a "Extra argument in call" error:

Picture of error here

Does anyone know what's going on?

0

3 Answers 3

271

Try making a Group { } around your views. Just 10 views are allowed in Swift UI, but with groups you can add more. Or use subviews (which would be cleaner code, too).

Sign up to request clarification or add additional context in comments.

Comments

27

The @ViewBuilder system in SwiftUI is limited to 10 views within any given view container. There's no argument for an 11th view, so you get that error.

The issue here is that your VStack is at maximum capacity, however you can wrap those existing views inside of other containers. As a very basic example that would allow you to show 10 BottomReceiptRow views:

 var body: some View { ZStack { Color.white .scaledToFit() // Modifications start here VStack { if adBannerView.adHasLoaded { adBannerView .frame(maxHeight: adBannerView.adHeight) .animation(.easeInOut(duration: 2.0)) } BorderView() Text(ARCHLocalizedStrings.receipt) .foregroundColor(Color.gray) BorderView() HStack { Spacer() Button(action: { self.receiptViewModel.addNewReceiptItem() }) { Text(ARCHLocalizedStrings.buttonTitleAddItem) } } BorderView() ScrollView { ForEach(receiptViewModel.receiptItems) { receiptItem in ItemView(receiptItem: receiptItem) if receiptItem != self.receiptViewModel.receiptItems.last { Divider() } } } BorderView() Group { BottomOfReceiptRow(receiptViewModel: receiptViewModel, type: ReceiptRowType.subtotal, title: ARCHLocalizedStrings.subtotal) BottomOfReceiptRow(receiptViewModel: receiptViewModel, type: ReceiptRowType.tax, title: ARCHLocalizedStrings.tax) BottomOfReceiptRow(receiptViewModel: receiptViewModel, type: ReceiptRowType.someValue, title: ARCHLocalizedStrings.someValue) BottomOfReceiptRow(receiptViewModel: receiptViewModel, type: ReceiptRowType.someValue2, title: ARCHLocalizedStrings.someValue2) BottomOfReceiptRow(receiptViewModel: receiptViewModel, type: ReceiptRowType.someValue3, title: ARCHLocalizedStrings.someValue3) BottomOfReceiptRow(receiptViewModel: receiptViewModel, type: ReceiptRowType.someValue4, title: ARCHLocalizedStrings.someValue4) BottomOfReceiptRow(receiptViewModel: receiptViewModel, type: ReceiptRowType.someValue5, title: ARCHLocalizedStrings.someValue5) } // Modifications end here } .padding(.horizontal, ARCHSwiftUILayoutConstants.defaultPaddingAndSpacing) } } 

Alternatively:

You may prefer to completely refactor these sections into their own View as composition makes the code easier to read. It's not strictly necessary here though.

If you did want to do that, you could consider an example where those receipt rows are all in their own view like:

 var body: some View { ZStack { Color.white .scaledToFit() VStack { if adBannerView.adHasLoaded { adBannerView .frame(maxHeight: adBannerView.adHeight) .animation(.easeInOut(duration: 2.0)) } BorderView() Text(ARCHLocalizedStrings.receipt) .foregroundColor(Color.gray) BorderView() HStack { Spacer() Button(action: { self.receiptViewModel.addNewReceiptItem() }) { Text(ARCHLocalizedStrings.buttonTitleAddItem) } } BorderView() ScrollView { ForEach(receiptViewModel.receiptItems) { receiptItem in ItemView(receiptItem: receiptItem) if receiptItem != self.receiptViewModel.receiptItems.last { Divider() } } } BorderView() bottomRow } .padding(.horizontal, ARCHSwiftUILayoutConstants.defaultPaddingAndSpacing) } } // Additional computed property in TipView var bottomRow: some View { Group { BottomOfReceiptRow(receiptViewModel: receiptViewModel, type: ReceiptRowType.subtotal, title: ARCHLocalizedStrings.subtotal) BottomOfReceiptRow(receiptViewModel: receiptViewModel, type: ReceiptRowType.tax, title: ARCHLocalizedStrings.tax) BottomOfReceiptRow(receiptViewModel: receiptViewModel, type: ReceiptRowType.someValue, title: ARCHLocalizedStrings.someValue) BottomOfReceiptRow(receiptViewModel: receiptViewModel, type: ReceiptRowType.someValue2, title: ARCHLocalizedStrings.someValue2) BottomOfReceiptRow(receiptViewModel: receiptViewModel, type: ReceiptRowType.someValue3, title: ARCHLocalizedStrings.someValue3) BottomOfReceiptRow(receiptViewModel: receiptViewModel, type: ReceiptRowType.someValue4, title: ARCHLocalizedStrings.someValue4) BottomOfReceiptRow(receiptViewModel: receiptViewModel, type: ReceiptRowType.someValue5, title: ARCHLocalizedStrings.someValue5) } } // end bottomRow 

Comments

2

In SwiftUI you can stack up to 10 views in the same Stack (VStack, HStack, ZStack), so you can Embed some Views inside another Stack or inside Group {}.

1 Comment

This just repeats existing answers. Please only add new answers when you have new information to share.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.