更新:我将代码更新到我以前的半工作解决方案,因为有多个答案,但没有一个回答了我需要它工作的问题。
另外,请注意,我需要美国在选择器的顶部,即使它再次出现在按字母顺序排列的国家列表中。
我正在尝试创建一个显示国家名称的选择器,并根据选择的国家/地区存储相应的国家/地区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()
}
}
}
我确信这是完全错误的方法,所以不要太担心纠正我的代码。我真的很想知道如何做到这一点,因为在选择美国州时,我还需要实现同样的事情(即显示州的全名但存储缩写)。
此外,身体视图还有更多内容,但我在这里删除了代码,只是为了说明这个具体问题。
提前感谢!
Picker
文档要求在每个Text
上使用标记
修饰符来控制皮克er
Picker在其选择
中存储的内容。
如果您只想存储选定的国家代码,那么没有理由存储一组国家名称。您应该使用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 })) { ... }