0

I have a view class showing list of items coming from ViewModel class, in picker. Initial state of this picker is first element from the array of objects of the viewModel class.

On selection of item from picker, I want to do different actions in that view - 1. send the object info to different screen on button click. 2. display information with respected to selected object from picker.

import SwiftUI
import Combine
struct SetConfiguration: View {


@ObservedObject var profileListVM : ProfilesListViewModel = ProfilesListViewModel()  
@State private var selectedConfiguration  = 0 ///show "Add" as initial state
var body: some View {
HStack {
        Text("Configuration:")

        Picker(selection: $selectedConfiguration.onChange(connectToConfiguration), label: EmptyView()) {
            ForEach(profileListVM.profiles, id: \.self) {
                          choice in
                Text(choice.name).tag(choice)
            }
        }

        Text (“Selcted item is: \(self. selectedconfiguration.name)”)

        Button(action: {

        }) {
            Text("Edit")
        }.sheet(isPresented: $showEditConfig) {
            EditConfigurationView()
                                         //  TODO pass  selectedConfiguration as profile object
        }

      }  

}

viewModel class:

class ProfilesListViewModel: ObservableObject { 
 @Published var profiles: [ProfileViewModel] = [ProfileViewModel]()   
static var addNewProfile = ProfileViewModel(name: "Add Configuration")
init() {
    fetchAllProfiles()
}
func fetchAllProfiles() {
     profiles.append(ProfilesListViewModel.addNewProfile) ///Add is first object
    self.profiles = CoreDataManager.shared.getConfigurations().map(ProfileViewModel.init) /// fetch all profile objects    
}

}

1 Answers1

2

I believe this is the context for your question. Here is the working example:

// MARK: MOCKS FOR MODELS
struct ProfileViewModel: Hashable {
    let id = UUID()
    let name: String
}

class CoreDataManager {
    static let shared = CoreDataManager()

    func getConfigurations() -> [ProfileViewModel] {
        return [ProfileViewModel(name: "first"), ProfileViewModel(name: "second"),  ProfileViewModel(name: "third")]
    }
}

// MARK: changed class because it's not even working because of lack of code
class ProfilesListViewModel: ObservableObject {

    @Published var profiles: [ProfileViewModel] = [ProfileViewModel]()
    static var addNewProfile = ProfileViewModel(name: "Add Configuration")

    init() {
        fetchAllProfiles()
    }

    func fetchAllProfiles() {
        print("fetched")
        profiles.append(ProfilesListViewModel.addNewProfile) ///Add is first object
        self.profiles = CoreDataManager.shared.getConfigurations()
    }

}

// MARK: the solution
struct SetConfiguration: View {

    @ObservedObject var profileListVM: ProfilesListViewModel = ProfilesListViewModel()
    @State private var selectedConfiguration = 0 ///show "Add" as initial state
    @State private var choosedConfiguration = 0

    var body: some View {

        VStack {

            HStack {

                Picker(selection: $selectedConfiguration.onChange(selectNewConfig), label: Text("Configuration")) {
                    ForEach(0 ..< self.profileListVM.profiles.count) { choice in
                        Text(self.profileListVM.profiles[choice].name).tag(choice)
                    }
                }
            }

            Text("Selected item is: \(choosedConfiguration)")

        }

    }

    func selectNewConfig(_ newValue: Int) {
        print(newValue)
        withAnimation {
            choosedConfiguration = newValue
        }

    }

}

Tips

To avoid misunderstandings in the future:

  1. you should add all the working code and links, or simplify it to be clear what you want to achieve. Not every swift developer know about extension Binding, so they will just say: onChange will not ever work and they will be right;

  2. format your code;

  3. add some examples of your models or remove/simplify them.

  4. I believe, you don't need choosedConfiguration, you can do some experiments with this.

halfer
  • 19,824
  • 17
  • 99
  • 186
Hrabovskyi Oleksandr
  • 3,070
  • 2
  • 17
  • 36