Learn Courses My Dashboard

User Input in Arrays in SwiftUI

I have been trying to write code to enable a user to input integer data into an Array, I am struggling with what should be a simple operation.

The Array is an EnvironmentObject comprised of 20 Integers.

I would like the User to the prompted to enter integer data for each item in the Array, from a single view within the App.

Can anyone assist with the code for this, or point me to where I can learn this?

Thanks.

This might give you an idea of how to do it.

Tapping the “+” icon presents a TextField at the bottom to enter a value

In this case the keyboard has been configured to be a NumberPad and since there is no return key, a “Save” button has been added so that when the user has keyed in the value, tapping the Save button adds the item to the array and the TextField disappears.

import SwiftUI

struct ContentView: View {
    @State private var integerArray = [Int]()
    @State private var itemToAdd = ""
    @State private var isAddingItem = false

    var body: some View {
        NavigationView {
            VStack {
                List {
                    ForEach(0..<integerArray.count, id: \.self) { item in
                        Text("\(integerArray[item])")
                    }
                }
                if isAddingItem {
                    Form {
                        Section(header: Text("Item to Add")) {
                            HStack {
                                TextField("Key in value", text: $itemToAdd)
                                    .keyboardType(.numberPad)
                                Button(action: {
                                    addItem()
                                }) {
                                    Text("Done")
                                }
                            }

                        }
                    }
                    .frame(height: 100)
                }
            }
            .listStyle(PlainListStyle())
            .navigationTitle("Integer Array")
            .navigationBarItems(
                trailing:
                    Button(action: {
                        isAddingItem = true
                    }) {
                        Image(systemName: "plus")
                            .padding(5)
                    }
            )
        }
    }

    func addItem() {
        if itemToAdd != "" {
            integerArray.append(Int(itemToAdd)!)
            itemToAdd = ""
        }
        isAddingItem = false
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

Thanks for it worked fantastic…

What additional coding do I need to add to place the “+” icon at the bottom of the page…?

You could add a toolbar at the bottom like this by adding this modifier to the Stack inside the NavigationView:

struct ContentView: View {
    @State private var integerArray = [Int]()
    @State private var itemToAdd = ""
    @State private var isAddingItem = false

    var body: some View {
        NavigationView {
            VStack {
                List {
                    ForEach(0..<integerArray.count, id: \.self) { item in
                        Text("\(integerArray[item])")
                    }
                }
                if isAddingItem {
                    Form {
                        Section(header: Text("Item to Add")) {
                            HStack {
                                TextField("Key in value", text: $itemToAdd)
                                    .keyboardType(.numberPad)
                                Button(action: {
                                    addItem()
                                }) {
                                    Text("Done")
                                }
                            }

                        }
                    }
                    .frame(height: 100)
                }
            }
            .listStyle(PlainListStyle())
            .navigationTitle("Integer Array")
            .navigationBarItems(
                trailing:
                    Button(action: {
                        isAddingItem = true
                    }) {
                        Image(systemName: "plus")
                            .padding(5)
                    }
            )
            .toolbar{
                ToolbarItem(placement: .bottomBar) {
                    Button(action: {
                        isAddingItem = true
                    }) {
                        Image(systemName: "plus")
                            .padding(5)
                    }
                }
            }
        }
    }

    func addItem() {
        if itemToAdd != "" {
            integerArray.append(Int(itemToAdd)!)
            itemToAdd = ""
        }
        isAddingItem = false
    }
}

Thanks, that worked really well.

How would I keep the NumberPad persisent to keep adding numbers into the Array, rather having having to enter + each time after selecting the Done button and the numberpad disappearing?

If the program is only ever dealing with integers (ie, no decimal values or negative values at all) then this might be the solution for you.

Keeping what I just said in mind, what I was concerned about was figuring out what the terminating condition needed to be to indicate that you had finished entering values. An option I see for this to work for you is to make the keyboard type a .decimalPad and make the terminating condition to be to input a decimal point on it’s own. If that’s a reasonable approach then this code works nicely.

struct ContentView: View {
    @State private var integerArray = [Int]()
    @State private var itemToAdd = ""
    @State private var isAddingItem = false

    var body: some View {
        NavigationView {
            VStack {
                List {
                    ForEach(0..<integerArray.count, id: \.self) { item in
                        Text("\(integerArray[item])")
                    }
                }
                if isAddingItem {
                    Form {
                        Section(header: Text("Item to Add")) {
                            HStack {
                                TextField("Key in value", text: $itemToAdd)
                                    .keyboardType(.decimalPad)
                                Button(action: {
                                    addItem()
                                }) {
                                    Text("Done")
                                }
                            }

                        }
                    }
                    .frame(height: 100)
                }
            }
            .listStyle(PlainListStyle())
            .navigationTitle("Integer Array")
            .navigationBarItems(
                trailing:
                    Button(action: {
                        isAddingItem = true
                    }) {
                        Image(systemName: "plus")
                            .padding(5)
                    }
            )
            .toolbar{
                ToolbarItem(placement: .bottomBar) {
                    Button(action: {
                        isAddingItem = true
                    }) {
                        Image(systemName: "plus")
                            .padding(5)
                    }
                }
            }
        }
    }

    func addItem() {
        if itemToAdd != "" && isNumeric(itemToAdd){
            integerArray.append(Int(itemToAdd)!)
            itemToAdd = ""
        } else if itemToAdd == "."{
            itemToAdd = ""
            isAddingItem = false
        }
    }

    func isNumeric(_ inputString: String) -> Bool {
        var count = 0
        let inputLength = inputString.count
        for item in inputString {
            switch item {
                case "0","1","2","3","4","5","6","7","8","9":
                    count += 1
                default:
                    break
            }
        }
        if count == inputLength {
            return true
        } else {
            return false
        }
    }
}