【问题标题】:Swift/Firebase - Unable to retrieve data in order that it was entered?Swift/Firebase - 无法按输入的顺序检索数据?
【发布时间】:2017-11-19 02:52:52
【问题描述】:

以与输入数据相同的顺序从 Firebase 检索数据时出现问题。我已经尝试了多种方法,使用 .valueAdded 和 .value 的不同变体以相同的顺序将其取回,但没有运气。也许我对这些数据建模的方式不正确?对此的任何帮助都会很棒。谢谢。

这是我的 Firebase 结构:

这是我的数据模型:

结构 RentalObjects {

var title = [String]()
var rentalType = [String]()
var dateAval = [String]()
var location = [String]()
var price = [String]()
var bond = [String]()
var pets = [String]()
var descripton = [String]()

}

这是我的表视图 VC:

导入 UIKit 导入 Firebase 数据库

RentalTableViewVC 类:UIViewController、UITableViewDataSource、UITableViewDelegate{

@IBOutlet weak var rentalImage: UIImageView!
@IBOutlet weak var tableView: UITableView!
@IBOutlet weak var rentalTitle: UILabel!
@IBOutlet weak var rentalPrice: UILabel!


var rentalsObject = RentalObjects()
var databaseRef:DatabaseReference?
var handle: DatabaseHandle?

var arrayOfTitles = [String?]()
var arrayOfBond = [String?]()
var arrayOfDateAval = [String?]()
var arrayOfDes = [String?]()
var arrayOfLocation = [String?]()
var arrayOfPets = [String?]()
var arrayOfPrice = [String?]()
var arrayOfRentalType = [String?]()



func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

    return rentalsObject.title.count

}

func numberOfSections(in tableView: UITableView) -> Int {
    return 1
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {



    let cell = UITableViewCell(style: .subtitle, reuseIdentifier: "cell")




    cell.textLabel?.text = ("Title: \(rentalsObject.title[indexPath.row]), DateAval: \(rentalsObject.dateAval[indexPath.row])")



    return cell
}


@IBAction func backPressed(_ sender: Any) {
    dismiss(animated: true, completion: nil)
}

override func viewDidLoad() {
    super.viewDidLoad()

    tableView.dataSource = self
    tableView.dataSource = self


    databaseRef = Database.database().reference().child("Rentals")
    databaseRef?.observe(.childAdded, with: { (snapshot) in


        if let dictonary = snapshot.value as? [String: AnyObject] {

            print(snapshot)




            switch snapshot.key {


            case "bond" :
                _ =  dictonary.map{self.rentalsObject.bond.append(($0.value as? String)!)}
                //      print(self.arrayOfBond)


            case "dateAval" :
                _ =  dictonary.map{self.rentalsObject.dateAval.append(($0.value as? String)!)}


            case "description" :
                _ =  dictonary.map{self.rentalsObject.descripton.append(($0.value as? String)!)}


            case "location" :
                _ =  dictonary.map{self.rentalsObject.location.append(($0.value as? String)!)}


            case "pets" :
                _ =  dictonary.map{self.rentalsObject.pets.append(($0.value as? String)!)}



            case "price" :
                _ =  dictonary.map{self.rentalsObject.price.append(($0.value as? String)!)}


            case "rentalType" :
                _ =  dictonary.map{self.rentalsObject.rentalType.append(($0.value as? String)!)}


            case "title" :
                _ =  dictonary.map{self.rentalsObject.title.append(($0.value as? String)!)}
                print(self.rentalsObject.title)


                //       _ =  dictonary.map{self.arrayOfTitles.append($0.value as? String)}
                //    print(self.arrayOfTitles)

            default:
                break

            }

        }



        DispatchQueue.main.async {
            self.tableView.reloadData()
        }



    })

}

}

这是我的 tableView 的输出示例。我试图按照它进来的顺序把它弄出来,在这个例子中,1、2、3、4、5。当我将来自其他变量的数据添加到此输出时,它们都因某种原因而混淆了。

这是将数据发送到 firebase 的代码:

类 AvertisingVC: UIViewController {

@IBOutlet weak var titleField: UITextField!
@IBOutlet weak var rentalTypeField: UITextField!
@IBOutlet weak var dateField: UITextField!
@IBOutlet weak var locationField: UITextField!
@IBOutlet weak var priceField: UITextField!
@IBOutlet weak var bondField: UITextField!
@IBOutlet weak var petsAllowedField: UITextField!
@IBOutlet weak var detailedDescription: UITextField!



var databaseRef:DatabaseReference?   //reference to firebase dba


override func viewDidLoad() {
    super.viewDidLoad()
    databaseRef = Database.database().reference().child("Rentals") //can add .child(string:root) to add root dir to dba
}

@IBAction func backBtnPressed(_ sender: Any) {
    self.dismiss(animated: true, completion: nil)
}


@IBAction func submitForm(_ sender: Any) {      // Send data to firebase on submit

    if titleField.text != nil {
        databaseRef?.child("title").childByAutoId().setValue(titleField.text)
        titleField.text = ""
    }

    if  rentalTypeField.text != nil {
        databaseRef?.child("rentalType").childByAutoId().setValue(rentalTypeField.text)
        rentalTypeField.text = ""
    }

    if  dateField.text != nil {
        databaseRef?.child("dateAval").childByAutoId().setValue(dateField.text)
        dateField.text = ""
    }

    if  locationField.text != nil {
        databaseRef?.child("location").childByAutoId().setValue(locationField.text)
        locationField.text = ""
    }

    if  priceField.text != nil {
        databaseRef?.child("price").childByAutoId().setValue(priceField.text)
        priceField.text = ""
    }

    if  bondField.text != nil {
        databaseRef?.child("bond").childByAutoId().setValue(bondField.text)
        bondField.text = ""
    }

    if  petsAllowedField.text != nil {
        databaseRef?.child("pets").childByAutoId().setValue(petsAllowedField.text)
        petsAllowedField.text = ""
    }

    if  detailedDescription.text != nil {
        databaseRef?.child("description").childByAutoId().setValue(detailedDescription.text)
        detailedDescription.text = ""
    }


    let alertController = UIAlertController(title: "Success!", message: "You have successfully listed a rental", preferredStyle: .alert)
    let defaultAction = UIAlertAction(title: "Close Alert", style: .default, handler: nil)
    alertController.addAction(defaultAction)

    present(alertController, animated: true, completion: nil)

}

}

【问题讨论】:

  • 添加保存数据的代码
  • 我已将此添加到主要问题中 - 感谢 svi.data!

标签: ios json swift firebase


【解决方案1】:

当从网络数据中解释数据时,如果它们在数组或字典中排序,则 swift 不保证解释值的顺序。您必须自己订购值,或更新缓存设备端,并在每次更新时对该缓存进行排序。

对于各种用例,有很多简单或复杂的方法。但是看看你的,在你调用delegatedatasource 方法之前,我会在你正在读取tableView 的数据源的任何地方添加一个sort。以您为例,如果您按日期排序:

override func viewDidLoad() {
    super.viewDidLoad()


    databaseRef = Database.database().reference().child("Rentals")
    databaseRef?.observe(.childAdded, with: { (snapshot) in


        if let dictonary = snapshot.value as? [String: AnyObject] {

            print(snapshot)

            switch snapshot.key {

            case "bond" :
                _ =  dictonary.map{self.rentalsObject.bond.append(($0.value as? String)!)}
                //      print(self.arrayOfBond)


            case "dateAval" :
                _ =  dictonary.map{self.rentalsObject.dateAval.append(($0.value as? String)!)}


            case "description" :
                _ =  dictonary.map{self.rentalsObject.descripton.append(($0.value as? String)!)}


            case "location" :
                _ =  dictonary.map{self.rentalsObject.location.append(($0.value as? String)!)}


            case "pets" :
                _ =  dictonary.map{self.rentalsObject.pets.append(($0.value as? String)!)}



            case "price" :
                _ =  dictonary.map{self.rentalsObject.price.append(($0.value as? String)!)}


            case "rentalType" :
                _ =  dictonary.map{self.rentalsObject.rentalType.append(($0.value as? String)!)}


            case "title" :
                _ =  dictonary.map{self.rentalsObject.title.append(($0.value as? String)!)}
                print(self.rentalsObject.title)


                //       _ =  dictonary.map{self.arrayOfTitles.append($0.value as? String)}
                //    print(self.arrayOfTitles)

            default:
                break

            }

        }

        whateverCollectionIsYourInCacheDataSource = whateverCollectionIsYourInCacheDataSource.sorted(by: { ($0, $1) -> Bool in
            return $0 < $1 //If you want to sort them by their date value. Make sure the dates are properly interpreted from whatever format they're saved in remotely into the Date type.
        })


        DispatchQueue.main.async {
            //No need to call .reloadData and these methods in viewDidLoad, unless you REALLY have to (ie: your data is modified on purpose after being loaded initially). Calling these methods loads up the data anyways, so just call these whenever your data is downloaded, converted and sorted properly.
            tableView.dataSource = self
            tableView.dataSource = self

        }



    })

}

希望它能帮助您走上正确的道路。查找基于网络的 tableview / collectionview 教程,它们会很有帮助。

【讨论】:

  • 感谢 murphguy,一定会查看基于网络的 tableview 教程并使用您提到的排序方法。我唯一的问题是我需要对齐这些数组,例如标题数组中的第三个元素与其他数组中的第三个元素相关,例如债券/价格等。所有这些属性都与单个出租元素相关。看起来这可能是不可能的,我可能不得不重新考虑如何建模/存储这些数据?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-04
  • 1970-01-01
  • 2020-04-22
  • 2017-06-24
  • 1970-01-01
相关资源
最近更新 更多