だから私はSwiftUIとCombineを学ぼうとしています。私は通常、簡単なチップ計算機を作ることから新しい技術を始めます。
ランダムに「呼び出し中の余分な引数」を取得しているようです。コーディング中のエラーここに私のSwiftUIファイルがあります
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())
}
}
ただし、TipViewボディ(任意のビュー)に別のビューを追加すると、「呼び出し中の余分な引数」エラーが発生するようです。
誰かが何が起こっているのか知っていますか?
SwiftUIの@ViewBuilderシステムは、特定のビューコンテナー内で10ビューに制限されています。 11番目のビューには引数がないため、エラーが発生します。
ここでの問題は、VStackの容量が最大になることですが、既存のビューを他のコンテナー内にラップできます。 10個のBottomReceiptRow
ビューを表示できるようにする非常に基本的な例として、
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)
}
}
構成によってコードが読みやすくなるため、これらのセクションを独自のView
に完全にリファクタリングすることをお勧めします。ただし、ここでは厳密には必要ありません。
これを実行したい場合は、次のように、それらの領収書行がすべて独自のビューにある例を検討できます。
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