UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

Can someone help me for a quick fix with this

Forums > SwiftUI

@onqun  

Can someone explain my mistake here, I have really having difficulty with propertywrappers.

import SwiftUI

struct ListView: View {
    @ObservedObject var item = Item(itemName: "dd", itemCount: 0)
    @State private var showingSheet = false

    var body: some View {
        List {
            Section(header: Text("List")) {
                ForEach(item) { item in

                    Text("\(item.itemName)")
                    Spacer()
                    Text("\(item.itemCount)")

                }
            }.headerProminence(.increased).listStyle(.insetGrouped)

            Section(header: Text("Add New Item")) {
                Button("Add New Item") { showingSheet.toggle() }.sheet(isPresented: $showingSheet) {
                    SheetView(newItemName: "", newItemCount: 0)
                        .interactiveDismissDisabled(true)
                        .presentationDetents([.fraction(0.4), .large]).presentationDragIndicator(.visible).presentationBackgroundInteraction(.enabled(upThrough: .medium))
                }
            }
        }
    }
}

#Preview {
    ListView(item: )
}

import Foundation import SwiftUI

class arrayOfItems: ObservableObject, Identifiable { @Published var listOfItems = [Item]()

func addnewItem(itemName: String, itemCount: UInt) {
    listOfItems.append(Item(itemName: itemName, itemCount: itemCount))
}

}

class Item: ObservableObject, Identifiable { @Published var itemName: String = "" @Published var itemCount: UInt = 0 @Published var id = UUID() @Published var group: String

init(itemName: String, itemCount: UInt) {
    self.itemName = "Enter Name"
    self.itemCount = 0
    self.group = ""
    id = UUID()
}

func add() {
    itemCount += 1
}

func sub() {
    itemCount -= 1
}

static var emptyItem: Item {
    Item(itemName: "Enter Name", itemCount: 0)
        }

}

2      

What exactly are the problems you are having with the code?

I see one problem with your code. Your list view has only one item.

@ObservedObject var item = Item(itemName: "dd", itemCount: 0)

You need an array of items to show in the list.

Another possible problem is using @ObservedObject for the property in the SwiftUI view. With classes you usually use @StateObject for a property in the view that owns the object and use @ObservedObject to pass that object to child views.

By the way the formatting is messed up for the code blocks that show the ArrayOfItems and Item classes. The blocks will be easier for people to read if you edit your question and fix the formatting.

3      

Where to start!! Other then what @SwiftDevJournal said

Tend to use struct in SwiftUI for data model so

struct Item: Identifiable {
    var id: UUID
    var itemName: String
    var itemCount: Int
    var group: String

    init(itemName: String, itemCount: Int, group: String = "") {
        self.id = UUID()
        self.itemName = itemName
        self.itemCount = itemCount
        self.group = group
    }

    mutating func add() {
        itemCount += 1
    }

    mutating func sub() {
        itemCount -= 1
    }

    static let emptyItem = Item(itemName: "Enter Name", itemCount: 0)
}

So the Data (arrayOfItems) becomes

class Data: ObservableObject, Identifiable {
    @Published var items = [Item]()

    func addNewItem(itemName: String, itemCount: Int) {
        items.append(Item(itemName: itemName, itemCount: itemCount))
    }
}

Changed @ObservedObject var item = Item(itemName: "dd", itemCount: 0) to @StateObject var data = Data() and ForEach(item) { item in to ForEach(data.items) { item in. Also add a HStack in your row.

struct ContentView: View {
    @StateObject var data = Data()
    @State private var showingSheet = false

    // For code example
    @State private var count = 0

    var body: some View {
        List {
            Section(header: Text("List")) {
                ForEach(data.items) { item in
                    HStack {
                        Text("\(item.itemName)")
                        Spacer()
                        Text("\(item.itemCount)")
                    }
                }
            }
            .headerProminence(.increased)
            .listStyle(.insetGrouped)

            Section(header: Text("Add New Item")) {
                Button("Add New Item") { showingSheet.toggle() }

                // For code example
                Button("Add Example Item") {
                    count += 1
                    data.addNewItem(itemName: "Example", itemCount: count)
                }
            }
        }
        .sheet(isPresented: $showingSheet) {
            Text("SheetView") // <- Just using this as SheetView not available
//            SheetView(newItemName: "", newItemCount: 0)
                .interactiveDismissDisabled(true)
                .presentationDetents([.fraction(0.4),.large])
                .presentationDragIndicator(.visible)
                .presentationBackgroundInteraction(.enabled(upThrough: .medium))
        }
    }
}

PS Added another button to add item to array to show list working

3      

@onqun  

thank you very mcuh for your help. I still have problem with appending array.

my sheet view


import SwiftUI

struct SheetView: View {
    @StateObject var data = Data()
    @Environment(\.dismiss) var dismiss

    @Binding var isSelected: Bool

    @State private var newItemName: String = ""
    @State private var newItemCount: UInt = 0
    @State private var overText = false

    var body: some View {
        VStack {
            Form {
                TextField("Item Name", text: $newItemName)
                    .accessibilityLabel("Item Name")
                TextField("Item Count", value: $newItemCount, format: .number)
                    .accessibilityLabel("Item Count")
                Button("Submit") {
                        self.isSelected = true
                        data.addnewItem(itemName: newItemName, itemCount: newItemCount)
                    print($newItemName)
                            dismiss()
                }
                .frame(maxWidth: .infinity, alignment: .center)
                .foregroundStyle(overText ? .green : .red)
                            .onHover { over in
                                overText = over
                            }
                .font(.title)
                .disabled(newItemName.isEmpty)
                .buttonStyle(.plain)

            }
        }
    }
}

#Preview {
    SheetView(isSelected: .constant(false))
}

My list view


import SwiftUI

struct ListView: View {

    @State private var showingSheet = false
    @StateObject var data = Data()

    var body: some View {
       List {
            Section(header: Text("List")) {
                ForEach(data.listOfItems) { item in

                    Text("\(item.itemName)")
                    Spacer()
                    Text("\(item.itemCount)")

                }

            }
            .headerProminence(.increased)
            .listStyle(.insetGrouped)

            Section(header: Text("Add New Item")) {
                Button("Add New Item") { showingSheet.toggle() }
                    .sheet(isPresented: $showingSheet) {
                        SheetView(isSelected: .constant(false))
                        .interactiveDismissDisabled(false)
                        .presentationDetents([.fraction(0.5), .large])
                        .presentationDragIndicator(.visible)
                        .presentationBackgroundInteraction(.enabled(upThrough: .medium))
                }
            }
        }
   }
}

#Preview {
    ListView()
}

2      

Both the list view and the sheet view have the following property in your code:

@StateObject var data = Data()

Both views have their own data property when they should be sharing one data property. When you add an item in the sheet view, the list view is not updating because you added the item to the sheet view's data property and not the list view's data property.

To fix the problem you must do two things. First, use the @ObservedObject property wrapper for the data property in the sheet view. Doing this will let you pass the data from the list view to the sheet view.

@ObservedObject var data: Data

Second, pass the data property to the sheet view when you show it.

SheetView(data: data, isSelected: .constant(false))

You might have to change the order of the arguments. Read the following Hacking with Swift article for more details on working with @ObservedObject:

How to use @ObservedObject to manage state from external objects

2      

TAKE YOUR SKILLS TO THE NEXT LEVEL If you like Hacking with Swift, you'll love Hacking with Swift+ – it's my premium service where you can learn advanced Swift and SwiftUI, functional programming, algorithms, and more. Plus it comes with stacks of benefits, including monthly live streams, downloadable projects, a 20% discount on all books, and free gifts!

Find out more

Sponsor Hacking with Swift and reach the world's largest Swift community!

Reply to this topic…

You need to create an account or log in to reply.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.