如何比较所选行的答案并从firebase检索答案?

时间:2017-02-25 07:51:34

标签: swift firebase swift3 firebase-realtime-database

我目前正在研究葡萄酒搜索器应用程序。基本上,我使用食物搭配葡萄酒。用户选择他最喜欢的食物。我有我的火力库数据库,存储标有特定葡萄酒名称和类型的葡萄酒数据。这是我在firebase中的json结构。

Wines:
  Wine1: 
   Name: Catena Zapata Malbec
   Type: Bold Red
  Wine2:
.......... etc.

我有另一个以前的视图控制器来选择喜欢的食物。例如,如果用户选择红肉,则相关的输入将为“Bold Red”。 所以,我做一个开关盒,例如:1(选择红肉),参考进入“Type”并搜索“Bold Red”,最后打印出该红酒的所有相关结果。

class Wine: NSObject{
    var name: String?
    var type: String?
    var foodChoice: String?
}


class ResultViewController: UITableViewController {

var ref: FIRDatabaseReference!
var refHandle: UInt!
var wineList = [Wine]()
var intPassed: Int!
let cellId = "cellId"

override func viewDidLoad() {

    super.viewDidLoad()

    navigationItem.title = "Results" 
    ref = FIRDatabase.database().reference()
    fetchWine() 
}


override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return wineList.count
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = UITableViewCell(style: .subtitle, reuseIdentifier: cellId)
    cell.textLabel?.text = wineList[indexPath.row].name

    return cell
}


func fetchWine(){
    switch intPassed {
    case 0:
        refHandle = ref.child("Wines").observe(.childAdded, with: { (snapshot) in
            if let dictionary = snapshot.value as? [String: AnyObject] {
                let wine = Wine()
                wine.name = dictionary["name"] as! String?
                wine.type = dictionary["type"] as! String?

                wine.setValuesForKeys(dictionary)
                self.wineList.append(wine)

                print (wine.name, wine.type)

                DispatchQueue.main.async {
                    self.tableView.reloadData()
                }
            }
        })
    case 1:
        refHandle = ref.queryOrdered(byChild: "Type").queryEqual(toValue: "Bold Red").observe(.value, with: {(snapshot) in
            if let dictionary = snapshot.value as? [String: AnyObject] {
            let wine = Wine()
            wine.name = dictionary["name"] as! String?

            wine.setValuesForKeys(dictionary)
            self.wineList.append(wine)

            print (wine.name)

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

        }
    })
default:
        print("nothing")

    }
}  
}

我可以打印案例0的数据。但是如果我想将所选类型的答案与数据库中的类型进行比较,我无法得到我想要的数据。它对refHandle的引用是错误的吗?

以下是针对案例0打印的结果。我只是确保firebase正常工作。其他选项只是我数据库中的其他葡萄酒。

0
Optional("Catena Zapata Malbec") Optional("Bold Red")
Optional("Merlot") Optional("Medium Red")
Optional("Pinot Noir") Optional("Light Red")

请帮忙!非常感谢!!

2 个答案:

答案 0 :(得分:1)

问题

我观察到的是refHandle似乎是正确的。但是你在observe块中访问错误的数据。

解决方案

案例1中的dictionary如下:

["Wine1": {
   name = "Catena Zapata Malbec";
   type = "Bold Red";
}]

这意味着,您需要访问另一个词典,以便在案例1中仅访问您的葡萄酒的名称Catena Zapata Malbec

case 1:
    refHandle = ref.queryOrdered(byChild: "Type").queryEqual(toValue: "Bold Red").observe(.value, with: {(snapshot) in
        if let dictionary = snapshot.value as? [String: AnyObject] {

          // Here access your name of the wine in the node
          if let wine1Dictionary = dictionary["Wine1"] as? [String: AnyObject] {
            let wine = Wine()
            wine.name = wine1Dictionary["name"] as! String?


            wine.setValuesForKeys(wine1Dictionary)
            self.wineList.append(wine)

            print(wine.name)
          }
    }
})

答案 1 :(得分:0)

让我们用一个结构,代码回答特定类型的葡萄酒和思想。

假设顾客正在吃肉或辛辣的晚餐,并希望有一些葡萄酒选择。他们知道大胆的红色是要走的路

你的葡萄酒结构如下;请记住,应使用childByAutoId()

生成父键
wines
  wine_id_0
    name: "Joseph Phelps Insignia"
    type: "Bold Red"
  wine_id_1
    name: "Heitz Cellers: Martha's Vineyard"
    type: "Bold Red"
  wine_id_2
    name: "Seasmoke Southing"
    type: "Fruity Red"

然后我们需要一个类或一个结构在这个案例中,我们可以存储在一个数组中,这个数组是tableView的dataSource,然后是加载葡萄酒时保存葡萄酒的数组。

struct WineStruct {
    var key = ""
    var name = ""
    var type = ""
}

var wineArray = [WineStruct]()

最后,一个详细的代码片段可以读入(在这种情况下)所有的Bold Red葡萄酒。

        let wineTypeToQuery = "Bold Red"
        let wineRef = ref.child("wines")
        let queryRef = wineRef.queryOrdered(byChild: "type")
                              .queryEqual(toValue: wineTypeToQuery)
        queryRef.observeSingleEvent(of: .value, with: { (snapshot) in

            for child in snapshot.children {
                let snap = child as! FIRDataSnapshot
                let wineDict = snap.value as! [String: Any]
                var wine = WineStruct()
                wine.name = wineDict["name"] as! String
                wine.type = wineDict["type"] as! String
                wine.key = snap.key
                self.wineArray.append(wine)
            }

            //here you would call tableView.reloadData()
            //do not use DispatchQueue!
            for wine in self.wineArray { //print the wines as a test
                let aWine = wine as! WineStruct
                let name = aWine.name
                let type = aWine.type
                print("\(name)  \(type)")
            }
        })

和结果输出

Joseph Phelps Insignia  Bold Red
Heitz Cellers: Martha's Vineyard  Bold Red

此代码将处理加载所有Bold Red葡萄酒以及每个葡萄酒子节点中保存的任何其他相关数据。上面的代码可以大大缩小(约为行数的1/2),但为了便于阅读,我留下了冗长的代码。

一个想法:

您可能想要考虑不同的结构,因为不同的葡萄酒可以搭配不同的食物。

例如:

wines
  wine_id_0
    name: "Joseph Phelps Insignia"
    type: "Bold Red"
    pairs_with:
      steak: true
      ribs: true
  wine_id_1
    name: "Heitz Cellers: Martha's Vineyard"
    type: "Bold Red"
    pairs_with:
      steak: true
      pork: true
  wine_id_2
    name: "Seasmoke Southing"
    type: "Fruity Red"
    pairs_with:
      cheese: true
      fish: true
    aromatics:
      spicey: true

通过这种结构,我们不会假设顾客知道Bold Red配牛排。他们可以选择牛排'我们以这种方式缩小结果。

当然,您可以进一步完善搜索,因为葡萄酒与肋眼配合得很好(它具有高脂肪含量并且真的需要更高的酒精来切穿它)可能与用Filet配对的葡萄酒不一样

我在最后一款葡萄酒上加入了芳香剂,因为它可以进一步缩小搜索范围 - 如果用户订购的是一种轻便的鱼,那通常可以叫到霞多丽或白苏维浓。然而,如果它以黑色(spicey)风格呈现,那么Pinot通常可以成为赢家。

希望有所帮助!喜欢应用程序概念!