I add item from this view :
struct InvoiceView: View {
@StateObject var itemsData = ItemsData()
@AppStorage("storeName") private var storeName = ""
@AppStorage("invoiceNumber") private var invoiceNumber = ""
@AppStorage("contactNumber") private var contactNumber = ""
@State private var invoiceDate = Date()
@AppStorage("customerName") private var customerName = ""
@AppStorage("customerAddress") private var customerAddress = ""
@AppStorage("cusContactNumber") private var cusContactNumber = ""
@State private var showingAddItem = false
@State private var showingHistoryView = false
// FOR CALCULATE TOTAL AMOUNT.
private var totalAmount: Double {
itemsData.items.reduce(0.0) { partialResult, item in
partialResult + item.price
// also can be expressed as { $0 + $1.amount }
}
}
// FOR CALCULATE DISCOUNT AMOUNT. (READING FROM AddView)
private var discountAmount: Double {
itemsData.items.reduce(0.0) { partialResult, item in
partialResult + item.discountAmount
// also can be expressed as { $0 + $1.amount }
}
}
// FOR CALCULATE VAT AMOUNT.
private var vatAmount1: Double {
itemsData.items.reduce(0.0) { partialResult, item in
if item.vat > 0 {
let netAmount = item.price / (1 + item.vat/100)
let vatamount = item.price - netAmount
return partialResult + vatamount
}
return partialResult
}
}
@State private var paymentM = "Cash"
let paymentsList = ["Cash", "BenefitPay", "Debit Card"]
@ObservedObject var historyData: historyData
@State private var type = "Income"
@ObservedObject var expenses: Expenses
var body: some View {
NavigationView {
List {
Section(header: Text("Store Details")) {
TextField("Store Name", text: $storeName)
TextField("Invoice number", text: $invoiceNumber)
TextField("contact number", text: $contactNumber)
}
Section{
DatePicker("Date", selection: $invoiceDate)
}
Section(header: Text("Customer Details")) {
TextField("Customer Name", text: $customerName)
TextField("Customer Address", text: $customerAddress)
TextField("contact number", text: $cusContactNumber)
}
Group {
Button{
showingAddItem = true
} label: {
HStack {
Image(systemName: "plus")
Text("Add Item")
}
}
.sheet(isPresented: $showingAddItem) {
AddView(ItemsData: itemsData)
}
ForEach(itemsData.items, id: \.id) { item in
HStack {
VStack(alignment: .leading) {
Text(item.name)
.lineLimit(3)
Text("x\(item.quantity.formatted())")
.foregroundColor(Color("grayed"))
}
Spacer()
VStack {
Text(item.price, format: .currency(code: Locale.current.currency?.identifier ?? "BD"))
.lineLimit(3)
}
}
}
.onDelete(perform: removeItem)
}
HStack {
Text("Discount amount")
Spacer()
Text("\(discountAmount.formatted(.currency(code: Locale.current.currency?.identifier ?? "BD")))")
.foregroundColor(.blue)
}
HStack {
Text("VAT amount")
Spacer()
Text("\(vatAmount1.formatted(.currency(code: Locale.current.currency?.identifier ?? "BD")))")
.foregroundColor(.red)
}
HStack {
VStack(alignment: .leading) {
Text("Total")
Text(vatAmount1 > 0 ? "inc. VAT" : "")
.foregroundColor(Color("grayed"))
}
Spacer()
Text("\(totalAmount.formatted(.currency(code: Locale.current.currency?.identifier ?? "BD")))")
.foregroundColor(.green)
}
Group {
Section {
Picker("payment method", selection: $paymentM) {
ForEach(paymentsList, id: \.self) {
Text($0)
}
}
}
}
}
.navigationTitle("Invoice Maker")
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItemGroup {
ShareLink("Export PDF", item: render())
Button("Save") {
let income = ExpenseItem(name: customerName, type: type, amount: totalAmount - vatAmount1, date: invoiceDate, vat: vatAmount1)
expenses.items.insert(income, at: 0)
let item = HistoryData(storN: storeName, storNum: contactNumber, invNum: invoiceNumber, dat: invoiceDate, cus: customerName, cusAddr: customerAddress, cusNum: cusContactNumber, price: totalAmount)
historyData.item.insert(item, at: 0)
}
}
Post
Replies
Boosts
Views
Activity
Hi @Claude31
struct ContentView: View {
@StateObject var expenses = Expenses()
var body: some View {
NavigationView {
List {
ForEach(expenses.items, id: \.id) { item in
HStack {
VStack(alignment: .leading) {
Text(item.name)
.font(.headline)
Text(item.type)
}
Spacer()
Text(item.amount, format: .currency(code: Locale.current.currency?.identifier ?? "BD"))
.foregroundColor(item.amount <= 10 ? .green : item.amount <= 100 ? .orange : .red)
}
}
.onDelete(perform: removeItem)
Add item code in AddView:
Button("Save") {
let item = ExpenseItem(name: name, type: type, amount: amount)
expenses.items.append(item)
}
I got the solution.
Changes to MainView:
struct MainView: View {
// Create your expenses object in the main view
@StateObject var expenses = Expenses()
// This is necessary for switching between tabs
@State var selectedTab = 0
var body: some View {
// Use selection initializer for TabView
TabView(selection: $selectedTab) {
ContentView()
.tabItem {
Image(systemName: "1.lane")
Text("One")
}
// we assign tag to programmatically switch between tabs
.tag(1)
// Also we pass selectedTab to AddView so that we can go back to ContentView programmatically
AddView(selectedTab: $selectedTab)
.tabItem {
Image(systemName: "2.lane")
Text("Two")
}
// we assign tag to programmatically switch between tabs
.tag(2)
}
// Inject expenses object into environment so that ContentView and AddView can access it
.environmentObject(expenses)
}
}
Changes to ContentView:
struct ContentView: View {
// This is how we can access expenses object in the environment
@EnvironmentObject var expenses: Expenses
var body: some View {
NavigationView {
List {
ForEach(expenses.items, id: \.id) { item in
HStack {
VStack(alignment: .leading) {
{....same......}
// Pay attention that you need to add .environmentObject in previews to make it work
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
.environmentObject(Expenses())
}
}
Changes to AddView:
struct AddView: View {
// This is how we can access expenses object in the environment
@EnvironmentObject var expenses: Expenses
@State private var name = ""
@State private var type = "personal"
@State private var amount = 0.0
// Here we pass selectedTab binding
@Binding var selectedTab: Int
let types = ["Business", "Personal"]
@Environment(\.dismiss) var dismiss
var body: some View {
NavigationView {
Form {
TextField("name", text: $name)
Picker("Type", selection: $type) {
ForEach(types, id: \.self) {
Text($0)
}
}
TextField("Amount", value: $amount, format: .currency(code: Locale.current.currency?.identifier ?? "BD"))
.keyboardType(.decimalPad)
}
.navigationTitle("Add new expense")
.toolbar {
Button("Save") {
let item = ExpenseItem(name: name, type: type, amount: amount)
expenses.items.append(item)
// This is how we jump back to ContentView upon pressing save
selectedTab = 1
}
}
}
}
}
// Pay attention that you need to add .environmentObject in previews to make it work
struct AddView_Previews: PreviewProvider {
static var previews: some View {
AddView(selectedTab: .constant(2))
.environmentObject(Expenses())
}
}
I got it from : https://www.hackingwithswift.com/forums/swiftui/list-isn-t-updating-when-i-add-a-new-item/23977/23981
This screenshot of iPhone 14 pro
Same issue using Xcode 15.0.1
Downgrade to Xcode 15.0