Swift dynamically create editable modal from Stepper component?

Swift dynamically create editable modal from Stepper component?

Problem Description:

I have a Stepper component that corresponds to number of people (for now, I don’t want to restrict what the stepper goes up to, but users will likely never enter more than 10). I want to dynamically generate a box that is essentially a Person object/class based on the current value of Stepper.

Current code

struct ContentView: View {
    @State private var numPeople = 0
    var body: some View {
        VStack {
            Text("Enter number of people below:")
            Stepper("(numPeople.formatted()) People", value: $numPeople)
        }
    }

Desired outcome if user clicks plus button until the number 3.

enter image description here

Should this be done using a for loop (or ForEach loop)? Should a component other than Stepper be used?

Solution – 1

There are a few different ways of doing this but for growth sake you can consider a PersonModel and basing the stepper on the count of Array<PersonModel> using a computed variable that adds and removes from the array.

import SwiftUI
struct PersonModel: Identifiable{
    let id: UUID = .init()
    let name: String
}
class PersonVM: ObservableObject{
    @Published var people: [PersonModel] = []
    
    var personCount: Int{
        get{
            //Single source of truth.
            people.count
        }
        set{
            let diff: Int = people.count - newValue
            
            if diff == 0{
                //No change
            } else if diff < 0 { //Add the difference
                let new: [PersonModel] = (0..<abs(diff)).map{ n in
                    PersonModel(name: "Person (people.count + n + 1)")
                }
                people.append(contentsOf: new)
            } else if !people.isEmpty{ //Remove the difference if the array isn't empty
                people.removeLast(diff)
            }
        }

    }
}

@available(iOS 15.0, *)
struct PersonView: View {
    @StateObject private var vm: PersonVM = .init()
    var body: some View {
        ScrollView {
            Text("Enter number of people below:")
            Stepper("(vm.people.count.formatted()) People", value: $vm.personCount, in: 0...10, step: 1)
            ForEach(vm.people) { person in
                ZStack{
                    Color.blue
                    Text(person.name)
                        .foregroundColor(.white)
                }.padding(2)
                
            }
        }
    }
}
Rate this post
We use cookies in order to give you the best possible experience on our website. By continuing to use this site, you agree to our use of cookies.
Accept
Reject