提问者:小点点

SwiftUI国家选择器-显示国家名称但存储国家ID


更新:我将代码更新到我以前的半工作解决方案,因为有多个答案,但没有一个回答了我需要它工作的问题。

另外,请注意,我需要美国在选择器的顶部,即使它再次出现在按字母顺序排列的国家列表中。

我正在尝试创建一个显示国家名称的选择器,并根据选择的国家/地区存储相应的国家/地区ID。这样,用户可以看到国家/地区的名称,但我只能将国家/地区ID传递到我的数据库中。

到目前为止,我拥有的代码显示了国家名称列表,并将该国家名称存储在选择的国家变量中。它还正确更新了HStack中的文本元素。

唯一不起作用的是存储相应的countryId。

我将SwiftUI与最新的Swift 5和XCode 13.1一起使用。

以下是我目前所获得的:

    import SwiftUI
        
            struct Country: View {
             
                @State private var selectedCountry = ""
                @State private var selectedCountryId = ""
             
                let countryId = Locale.isoRegionCodes
                let countryArray = Locale.isoRegionCodes.compactMap { Locale.current.localizedString(forRegionCode: $0) }
            
                var body: some view {
    
                    HStack {
                        Text("Country:")
                            .font(.system(size: 17))
                        Spacer()
                                    
                        Text("")
                        if selectedCountry != "" {
                            Text("\(selectedCountry)")
                                .font(.system(size: 17))
                                .foregroundColor(Color("WhiteText"))
                        } else {
                              Text("Select Country")
                                  .font(.system(size: 17))
                                  .foregroundColor(Color("GrayText"))
                        }
                                    
                     } // End HStack
                                
                     .onTapGesture {
                         self.showsCountryPicker.toggle()
                     }
             
                Picker("Country", selection: $selectedCountry) {
                        ForEach(countryArray, id: \.self) {
                            Text($0)
                            }
                        }
                        .pickerStyle(WheelPickerStyle())
                        .padding()
                        .labelsHidden()
                     }
}
}

我确信这是完全错误的方法,所以不要太担心纠正我的代码。我真的很想知道如何做到这一点,因为在选择美国州时,我还需要实现同样的事情(即显示州的全名但存储缩写)。

此外,身体视图还有更多内容,但我在这里删除了代码,只是为了说明这个具体问题。

提前感谢!


共3个答案

匿名用户

Picker文档要求在每个Text上使用标记修饰符来控制皮克erPicker在其选择中存储的内容。

如果您只想存储选定的国家代码,那么没有理由存储一组国家名称。您应该使用SwiftUI的< code>Environment来获取当前的< code>Locale,这样,如果用户更改了她的Locale,您的视图就会被重新绘制。

import SwiftUI
import PlaygroundSupport

struct CountryPicker: View {
    @Binding var countryId: String
    @Environment(\.locale) var locale
    
    var body: some View {
        Picker("", selection: $countryId) {
            ForEach(Locale.isoRegionCodes, id: \.self) { iso in
                Text(locale.localizedString(forRegionCode: iso)!)
                    .tag(iso)
            }
        }
    }
}

struct Test: View {
    @State var countryId: String = ""
    
    var body: some View {
        VStack {
            CountryPicker(countryId: $countryId)
            Text("You picked \(countryId).")
        }
        .padding()
    }
}

PlaygroundPage.current.setLiveView(Test())

匿名用户

我很感激所有的帮助,但我得到了我想要的一切。为此,我只存储了国家ID,这是我所需要的,但是将该ID转换为HStack中文本元素的国家名称。

答案如下:

import SwiftUI

// Struct to store the country name and ID

fileprivate struct Country {
    var id: String
    var name: String
}

// Function to put United States at the top of the list

fileprivate func getLocales() -> [Country] {
    let locales = Locale.isoRegionCodes
        .filter { $0 != "United States"}
        .compactMap { Country(id: $0, name: Locale.current.localizedString(forRegionCode: $0) ?? $0)}
    return [Country(id: "US", name: Locale.current.localizedString(forRegionCode: "US") ?? "United States")] + locales
}

struct Test: view {

// selectedCountry stores the countryID (i.e. US)
    @State private var selectedCountry: String = ""
    
 // Main UI
    
    var body: some View {

        HStack {
            Text("Country:")
                .font(.system(size: 17))
            Spacer()
                                
            Text("")
            if selectedCountry != "" {
                Text(Locale.current.localizedString(forRegionCode: selectedCountry) ?? selectedCountry)
                    .font(.system(size: 17))
                    .foregroundColor(Color("WhiteText"))
             } else {
                   Text("Select Country")
                       .font(.system(size: 17))
                       .foregroundColor(Color("GrayText"))
               }
                                
             } // End HStack

             Picker("Country", selection: $selectedCountry) {
                 ForEach(getLocales(), id: \.id) { country in
                 Text(country.name).tag(country.id)
                 }
             }

}
}

匿名用户

我只想做一些简单的事情:

struct Country: Identifiable, Hashable {
    let id: String
    let name: String
}

struct CountryView: View {
    let countries = Locale.isoRegionCodes.compactMap{
        Country(id: $0, name: Locale.current.localizedString(forRegionCode: $0)!) }
    
    @State var selectedCountry: Country?
    
    var body: some View {
        Picker("Country", selection: $selectedCountry) {
            ForEach(countries) {
                Text($0.name).tag(Optional($0))
            }
        }.pickerStyle(.wheel)
            .onChange(of: selectedCountry) { selected in
                if let cntry = selected {
                    print("--> store country id: \(cntry.id)")
                }
            }
    }
}

如果要对国家进行排序,请使用以下命令:

ForEach(countries.sorted(by: { $0.name < $1.name })) { ... }