0

I have a SwiftUI View called CountryPicker that I am using within a UIKIT project.

The CountryPicker works correctly within a pure SwiftUI project.

The problem is, when I try to use the same CountryPicker within UIKIT using

UIHostingController, the actual selection change from the CountryPicker is not applied. For example, if the default country is United Kingdom, and I selected United States, then United States would not be display as the default country in the CountryPicker. As mentioned above in SwiftUI project it works correctly.


struct CountryPicker: View {
    let countries: [String]
    @Binding var selectedCountry: String
    @Binding var selectedCountryIndex: Int
    @State private var isPickerVisible = false
    var onSelect: ((Int) -> Void)?
    var body: some View {
        HStack {
            Text("Country")
            Spacer()
            Menu {
                Picker(selection: $selectedCountryIndex, label: Text("")) {
                    ForEach(0..<countries.count,  id: \.self) { index in
                        Text(countries[index]).tag(index)
                    }
                }
                .pickerStyle(DefaultPickerStyle())
                .onChange(of: selectedCountryIndex) { index in
                    selectedCountry = countries[index]
                    onSelect?(index)
                }
            } label: {
                HStack {
                    Text(selectedCountry.isEmpty ? "United Kingdom" : selectedCountry)
                        .foregroundColor(.primary)
                    Image(systemName: "chevron.down")
                        .foregroundColor(.primary)
                }
                .padding()
                .background(SwiftUI.Color.clear)
                .cornerRadius(10)
            }  .frame(width: 200, height: 10)
            Spacer()
        }
        .onAppear {
            selectedCountry = countries[selectedCountryIndex]
            isPickerVisible = true
        }
    }
}


 // Create an instance of CountryPicker and pass the required bindings and data
        let picker = CountryPicker(
            countries: countries, // List of countries
            selectedCountry: Binding<String>( // Binding for the selected country
                get: { self.selectedCountry2 }, // Getter: Returns the selected country
                set: { newValue in // Setter: Updates the selected country
                    self.selectedCountry2 = newValue
                }
            ),
            selectedCountryIndex: Binding<Int>( // Binding for the selected country index
                get: { self.selectedCountryIndex }, // Getter: Returns the selected country index
                set: { newValue in // Setter: Updates the selected country index
                    self.selectedCountryIndex = newValue
                    self.selectedCountry2 = self.countries[newValue] // Update the selected country based on the index
                    debugPrint("Selected Country: \(self.selectedCountry2)")
                }
            ),
            onSelect: { index in
                // Handle the selected country index
            }
        )

        // Set the initial value of selectedCountryIndex to match the index of the selected country
        if let index = countries.firstIndex(of: selectedCountry2) {
            selectedCountryIndex = index
        }

        // Create a UIHostingController and set its rootView as the CountryPicker instance
        countryPicker = UIHostingController(rootView: picker)

        // Add the UIHostingController as a child view controller
        if let countryPicker = countryPicker {
            addChild(countryPicker)
            view.addSubview(countryPicker.view)
            countryPicker.didMove(toParent: self)

            // Set up constraints for the countryPicker.view
            countryPicker.view.translatesAutoresizingMaskIntoConstraints = false
            NSLayoutConstraint.activate([
                countryPicker.view.topAnchor.constraint(equalTo: addressView.bottomAnchor, constant: 0),
                countryPicker.view.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 1.0),
                countryPicker.view.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -1.0),
                countryPicker.view.heightAnchor.constraint(equalToConstant: 50.0)
              
            ])
        }

        


Look forward to your response.

Thanks

CableGuy
  • 47
  • 1
  • 6
  • This needs a [mre]. Presumably, there's something wrong with your UIKit implementation, but there's a lot left to the imagination here. My assumption is that you don't have anything set up to trigger an update your `View` when `selectedCountry2` updates. My suggestion would be to store your state in an `ObservableObject` (with `@Published` properties) owned by the UIKit View and pass it into SwiftUI – jnpdx Jul 06 '23 at 20:19
  • `Binding` is only for SwiftUI `View`s, it does not work in a `class` you need an alternate way of communicating such as a delegate, a shared source of truth, completion handers, etc – lorem ipsum Jul 06 '23 at 21:36

0 Answers0