Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/video/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 如何在UIPickerView中加载从Firebase检索的数据?_Ios_Swift_Firebase_Swift3_Firebase Realtime Database - Fatal编程技术网

Ios 如何在UIPickerView中加载从Firebase检索的数据?

Ios 如何在UIPickerView中加载从Firebase检索的数据?,ios,swift,firebase,swift3,firebase-realtime-database,Ios,Swift,Firebase,Swift3,Firebase Realtime Database,我用bookingInfo中的数据填充UIPickerView,它可以按预期工作。但是,我需要在UIPickerView中再添加一行,并为其指定一个默认值。 为了在numberOfRowsInComponent中执行此操作,我返回bookingInfo.count+1 问题是我在switch语句中得到的错误索引超出了范围。我不确定这是否是因为firebase异步检索数据 class ContactUs: UIViewController, UIPickerViewDelegate, UIPick

我用bookingInfo中的数据填充UIPickerView,它可以按预期工作。但是,我需要在UIPickerView中再添加一行,并为其指定一个默认值。 为了在numberOfRowsInComponent中执行此操作,我返回bookingInfo.count+1 问题是我在switch语句中得到的错误索引超出了范围。我不确定这是否是因为firebase异步检索数据

class ContactUs: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {

var currentUid:String!
var dbRef:FIRDatabaseReference! 
var bookingInfo = [FireBaseData]() // this array will hold all bookings for the logged in user
@IBOutlet weak var bookingsPickerView: UIPickerView!

 override func viewDidLoad() {
    super.viewDidLoad()

    bookingsPickerView.delegate = self
    bookingsPickerView.dataSource = self

    guard let uid = FIRAuth.auth()?.currentUser?.uid else {
        return
  }
    self.currentUid = uid
    dbRef = FIRDatabase.database().reference().child("Cleaners")
    startObservingDB() // observe the database for value changes
}//end of viewDidLoad


   func numberOfComponents(in pickerView: UIPickerView) -> Int {
       return 1
  }

    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
    return bookingInfo.count + 1 //if I don't add 1 my code will run properly
 }

 func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView {

    let label = UILabel(frame: CGRect(x: CGFloat(0), y: CGFloat(0), width: CGFloat(300), height: CGFloat(37)))

    if bookingInfo.isEmpty == false {

        switch row{
         case 0...bookingInfo.count:
            //Prints index out of range
            let booking = self.bookingInfo[row]
            label.text = String(booking.BookingNumber) + " " + String(booking.DateAndTime)

        default:
            label.text = "default Value"
        }   
     }
     return label
   }
}// end of class ContactUs



extension ContactUs {

//observe firebase at a specific reference for values changes
func startObservingDB() {

    dbRef.child(currentUid).child("bookings").observe(.value, with: { (snapshot: FIRDataSnapshot) in

        //instance of FireBaseData holding all bookings under currentUid
        var newBookingInfo = [FireBaseData]()


            //iterate over each booking which is located under 'bookings'
            for booking in snapshot.children {
                var bookingItem = FireBaseData(snapshot: booking as! FIRDataSnapshot)
                newBookingInfo.append(bookingItem) 
            } 

        //assign newBookingInfo to global variable
        self.bookingInfo = newBookingInfo

   //sort the array in place so that the most recent date will appear first
        self.bookingInfo.sort(by: {(DateAndTimeObject_1,DateAndTimeObject_2) -> Bool in  
            DateAndTimeObject_1.TimeStampDateAndTime > DateAndTimeObject_2.TimeStampDateAndTime
        })

        // after Firebase retrieves all bookings, reload the componets in the picker view so that the methods belonging to protocol UIPickerViewDelegate will be called
        self.bookingsPickerView.reloadAllComponents()
    }, withCancel: { (Error:Any) in
        print("Error firebase \(Error)")
    })  
 } // end of startObservingDB()

}//end of extension
更新

多亏了@livtay,我的代码才起作用。当bookingInfo数组不是空的,而不是现在显示的最后一行时,如何在第一行显示其他值? 我的进步到目前为止

   func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView {

    let label = UILabel(frame: CGRect(x: CGFloat(0), y: CGFloat(0), width: CGFloat(300), height: CGFloat(37)))
        label.textAlignment = .left     

    if bookingInfo.isEmpty == true {
         label.text = "Other"
         self.pickerViewTitle = "Other"

        } else {

        switch row{
          case 0...bookingInfo.count - 1:
              let booking = self.bookingInfo[row]
              self.pickerViewTitle = String(booking.BookingNumber) + " " + String(booking.DateAndTime)
              label.text = self.pickerViewTitle

        default:
            label.text = "Other"
             self.pickerViewTitle = "Other"
        }
    }
    return label 
}
试着改变

case 0...bookingInfo.count:

因为数组的计数中包含0。 例如,如果数组有1个对象,则将计算0…1,但数组中唯一的索引是0

编辑:问题的第二部分:

在switch语句中,将默认情况下的代码置于

case 0:
然后剩下的在下面

case 1...bookingInfo.count:
您需要将逻辑更改为:

let booking = self.bookingInfo[row - 1]

它起作用了。如何获取默认值作为第一行不完整项?谢谢使用picker view selectRow函数@bibscy@Parama达尔米卡我的意思不是将默认值选作第一行,而是在UIPickerView中实际显示为第一个选项。
let booking = self.bookingInfo[row - 1]