简体   繁体   中英

Can't retrieve data from Firebase with Swift

I am trying to create a view controller displaying information of the clicked shop from a UITableView on the previous view controller. However, I cannot retrieve data in the new view controller and I don't know how to solve this issue. Here is my database structure. Thank you for the help. 数据库结构

import UIKit
import Firebase
import FirebaseDatabase

class ShopViewController: UIViewController {    
    var name :String? // This is the name of the cell clicked on the previous viewcontroller

    var ref: DatabaseReference!
    @IBOutlet weak var shopName: UILabel!    
    @IBOutlet weak var shopType: UILabel!    
    @IBOutlet weak var imageView: UIImageView!

    override func viewDidLoad() {
        shopName.text = name

        let ref = Database.database().reference().child("shops").childByAutoId().child(name!).child("Details")

        ref.observe(.childAdded, with: { snapshot in            
            let snapshotValue = snapshot.value as! NSDictionary
            let imageUrlString = snapshotValue["imageURL"] as! String
            print(imageUrlString)
            let shoptype = snapshotValue["type"] as! String
            self.shopType.text = shoptype            
        })
    }
}

The reference that you have is wrong, childByAutoId() is used to generate a unique id in your database.

Also the id that you currently have is the userid, you need to retrieve the userid:

let user = Auth.auth().currentUser
let uid = user.uid

then the location should be:

let ref = Database.database().reference().child("shops").child(uid).child("Eat").child("Details")

So there's a couple of issues here, first off is your data structure.

Something along these lines would be much easier to read from. You shouldn't need the name field as far as I can tell, and is there a requirement to have the details nested?

在此处输入图片说明

Reading the data

Next up, you can refactor your data reference code. I'd firstly recommend extracting the logic into its own method rather than having it directly in viewDidLoad :

var ref: DatabaseReference!

override func viewDidLoad() {
    shopName.text = name
    self.ref = Database.database().reference()
    getShopDetails()
}

func getShopDetails() {
  guard let shopName = name else { return }
   ref.child("shops").child(shopName).observe(.childAdded, with: { snapshot in         
        guard let shop = snapshot.value as? [String: AnyObject] else { return }

        let imageUrlString = shop["imageURL"] as! String
        print(imageUrlString)
        let shoptype = shop["type"] as! String
        self.shopType.text = shoptype            
    })
}

I've modified to set the database reference value as otherwise this would crash if you tried to use it elsewhere. I've also added a couple of guard statements to minimise the number of explicit unwraps.

I can't comment on your list code, but have you considered doing the call for all of the shops in this, and mapping the result to a data object, which you can then use to display the data in the screen we're detailing here, rather than doing a separate query every-time you open a detail screen.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM