[英]How to place nodes of Firebase Data in Array
在我的應用程序的第一頁上,我使用的是UIViewPicker,它允許用戶選擇他們想要選擇的國家。 而不是我通過數組將國家/地區名稱硬編碼到UIPicker中(如下所示):
var country = ["USA", "CANADA"]
我認為最好將應用程序連接到我的Firebase數據庫,在該數據庫中可以獲取所有國家/地區,然后將其附加到數組中,並從中讀取UIPicker。
這樣,如果我想添加更多的國家/地區,則無需發布新版本的應用程序。 我只需在數據庫中添加另一個國家,應用程序就會自動更新它。 但是我不確定如何做到這一點。 當我打印數據庫快照時,我得到了整個數據庫,但是我只是想將美國和加拿大放入一個陣列中。
所以這是我的firebase數據庫的結構:
countries
Canada
states
Alberta
British Columbia
USA
states
Alabama
Arkansas
這是我當前的代碼:
import UIKit
import FirebaseDatabase
class ViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {
@IBOutlet weak var countryPicker: UIPickerView!
//let country = ["USA", "Canada"] I am no longer using this hardcoded array
var countrySelected = String()
var action = 0
override func viewDidLoad() {
super.viewDidLoad()
//this is where I reach out to the database
let database = Database.database().reference()
database.child("countries").observeSingleEvent(of: .value) { (Snapshot) in
print(Snapshot)
}
//add code here that takes the snapshot and appends the the array below
var country = string()
countrySelected = country[0]
countryPicker.selectRow(action, inComponent: 0, animated: false)
//print(countrySelected)
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return country.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return country[row]
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
countrySelected = country[row]
action = country.firstIndex(of: countrySelected)!
//print(countrySelected)
}
}
如果有人可以幫助解釋,那就太好了!
為了使事情變得容易,我們可以創建一些結構來代表國家和州。
struct Country {
struct State {
let country: String
let name: String
}
let name: String
let states: [State]
static var ref: DatabaseReference {
return Database.database().reference(withPath: "countries")
}
static func from(key: String, value: Any?) -> Country? {
guard
let value = value as? [String:[String]],
let states = value["states"] else { return nil }
return Country(name: key, states: states.map {
State(country: key, name: $0)
})
}
static func countries(from snapshot: DataSnapshot) -> [Country]? {
return snapshot.snapshots.compactMap {
Country.from(key: $0.key, value: $0.value)
}
}
}
對DataSnapshot
的擴展使我們可以方便地訪問快照的子級。
extension DataSnapshot {
var snapshots: [DataSnapshot] {
return children.allObjects as? [DataSnapshot] ?? []
}
}
接下來,我們創建一些屬性來處理國家/地區–一個存儲它們的數組以及一些計算出的屬性以返回所選國家和州。
class CountryStatePickerViewController: UIViewController {
// MARK: Outlets
@IBOutlet weak var pickerView: UIPickerView! {
didSet {
loadCountries()
}
}
// MARK: Properties
private var countries = [Country]() {
didSet {
pickerView.reloadAllComponents()
}
}
var selectedCountry: Country? {
return country(at: pickerView.selectedRow(inComponent: 0))
}
var selectedState: Country.State? {
return selectedCountry.flatMap {
state(at: pickerView.selectedRow(inComponent: 1), in: $0)
}
}
}
我們還需要一些方法來安全地訪問特定索引下的國家和州,以及一種首先加載國家/地區的方法。
extension DataSnapshot {
var snapshots: [DataSnapshot] {
return children.allObjects as? [DataSnapshot] ?? []
}
}
extension CountryStatePickerViewController {
private func loadCountries() {
Country.ref.observeSingleEvent(of: .value, with: { [weak self] in
self?.countries = Country.countries(from: $0) ?? []
})
}
private func country(at index: Int) -> Country? {
return countries.indices.contains(index) ? countries[index] : nil
}
private func state(at index: Int, in country: Country) -> Country.State? {
return country.states.indices.contains(index) ? country.states[index] : nil
}
}
最后,在我們的UIPickerView
協議一致性中,countries數組填充了數據源。 我們可以使用兩個組件來代表國家及其相應的州。
extension CountryStatePickerViewController: UIPickerViewDataSource, UIPickerViewDelegate {
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 2
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
switch component {
case 0:
return countries.count
case 1:
return selectedCountry?.states.count ?? 0
default:
return 0
}
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
switch component {
case 0:
return country(at: row)?.name
case 1:
return selectedCountry.flatMap { state(at: row, in: $0)?.name }
default:
return nil
}
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if component == 0 { pickerView.reloadComponent(1) }
selectedState.flatMap { print($0.name, $0.country) }
}
}
var countries : [Any] = []
override func viewDidLoad() {
super.viewDidLoad()
database.child("countries").observeSingleEvent(of: .value) { (snapshot) in
if snapshot.exists() {
if let dict : [String : AnyObject] = snapshot.value as? [String : AnyObject] {
let array : [Any] = (dict as AnyObject).allValues
self.countries = array
// reload countryPicker data
}
}
else {
// not exist in db
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.