我正在嘗試創建一個顯示國家/地區名稱的選擇器,并根據選擇的國家/地區存盤相應的國家/地區 ID。通過這種方式,用戶可以看到國家/地區的名稱,但我只能將國家/地區 ID 傳遞到我的資料庫中。
我創建了兩個陣列(一個用于國家名稱,一個用于國家 ID),并使用 zip 和結構將它們組合成一個陣列。這在沒有視圖輸出 Country.init 轉儲的操場上作業,但在我的 swift.view 檔案中,它引發了各種錯誤。
我將 SwiftUI 與最新的 Swift 5 和 XCode 13.1 一起使用。
這是我到目前為止所得到的:
import SwiftUI
struct Country: View {
@State private var selectedCountry = ""
@State private var selectedCountryId = ""
var countryId = Locale.isoRegionCodes
var countryName = Locale.isoRegionCodes.compactMap { Locale.current.localizedString(forRegionCode: $0) }
struct Countries { let countryId: String; let countryName: String }
countryId.insert("US", at:0)
countryName.insert("United States", at:0)
zip(countryId, countryName).map(Countries.init)
var body: some view {
Picker("Country", selection: $selectedCountry) {
ForEach(Self.Countries(Countries.init), id: \.countryName) {
Text($0)
}
}
}
我確信這是完全錯誤的方法,所以不要太擔心更正我的代碼。我真的很想知道如何做到這一點,因為在選擇美國州時我還需要執行相同的操作(即顯示州的全名但存盤縮寫)。
此外,身體視圖還有更多內容,但我已在此處精簡代碼以顯示此特定問題。
提前致謝!
uj5u.com熱心網友回復:
這就是我的朋友字典派上用場的地方。字典由兩部分組成Key,Value或者簡單["Key":"Value"]地說,關于字典有三件事情需要注意。
- #1,所有鍵值對必須是相同的型別,例如,
[32:"String", 33: "String"]記住哪個很重要。 - #2,它不保證順序。
- #3,它只能包含唯一鍵。
這如何適用于您的問題?嗯,這與您擁有的資料型別有關。目前你有 2 個獨立的陣列,一個是國家,一個是代碼。您可以將它們組合到字典中并確保它們始終在一起,從鍵中參考值,或搜索值,以獲取一個鍵或多個鍵。前一句很重要,盡管不適合您的情況,但您可以保證只為一個鍵獲取一個值,但您可以從一個值獲取多個鍵。在您的情況下,您有一個唯一的國家/地區和唯一的 ID。
var countries = ["USA": 9999,
"UK": 9998,
"Canada": 9997] // Etc..
從字典中獲取值更容易,但作業方式類似于陣列。你給它下腳本。例如:
var canadaID= countries["Canada"]
現在從值中獲取鍵變得更加棘手,因為您必須遍歷整個字典才能獲取它。也有可能存在重復值,這意味著您可以從技術上取回“鍵”陣列。在這個例子中,我只抓取了第一個找到的值。再次記住,順序是不能保證的,如果你有多個相同的值,你可能會得到不正確的密鑰。
var countryID = 9998
if let key = countries.first(where: { $0.value == someValue })?.key {
print(key)
}
從這里開始存盤它變得微不足道。
func storeCountryIDFromKey(country: String) {
let countryId = countries[country]
// Store your ID.
}
如果我的訂單很重要怎么辦????
這對您的情況可能很重要,因為您可能希望按字母順序顯示國家/地區。要做到這一點,只需按照傳統將鍵映射到陣列并排序。
let keys: [String] = countries.map{String($0.key) }
補充閱讀
編程中有一個概念叫做 Big-O 表示法,通常表示為 O(n)或發音為 O-of-N。這就是我們描述時間和空間復雜性的方式。如果您想成為一名出色的開發人員,那么學習它是一項很棒的技能,因為它與資料結構和演算法有關。為了使這一點更有意義,因為它適用于您的問題,有兩個單獨的陣列來回圈,而一個字典實際上需要 2 倍的時間來完成雙陣列。此外,它使空間復雜度加倍。將兩者合并為一個 Dictionary 將性能開銷降低 1/2,這是一個巨大的性能提升。對于像國家這樣數量有限的小資料集,這并不重要;但是,如果您開始處理大量資料集,那么速度突然提高 1/2 是一個顯著的性能提升。
無需深入研究,只需讓您的輪子旋轉,每次您創建變數或編譯器為您執行此操作時,都會增加空間復雜性。每次運行一行代碼或遍歷一行代碼時,都會增加時間復雜度。總是,我的意思是總是,盡力減少開銷。它會迫使你跳出框框思考,反過來,你會學到更好的做法。
uj5u.com熱心網友回復:
該Picker檔案說,使用tag修改器上的每個Text控制什么Picker在其商店selection。
如果您只想存盤選定的國家/地區代碼,則沒有理由存盤國家/地區名稱陣列。并且您應該使用 SwiftUIEnvironment來獲取當前的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())
uj5u.com熱心網友回復:
我會做一些像這樣簡單的事情:
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 })) { ... }
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/372524.html
上一篇:如何設定約束使標簽填滿整個螢屏?
下一篇:單擊按鈕打開記錄器
