如何在 Firebase 中显示 autoID 子项下的数据?

Posted

技术标签:

【中文标题】如何在 Firebase 中显示 autoID 子项下的数据?【英文标题】:How to display data in Firebase that is held under a autoID child? 【发布时间】:2016-12-04 01:48:27 【问题描述】:

我正在创建一个库存应用程序来跟踪实验室中的物品。在实验室中有不同的站点,其中包含不同的项目,如您所见,这些站点在我的 Firebase 数据库中结构正确。

Firebase Database

Iphone Simulator

当我尝试从 tableCell 中删除特定项目时,我的问题就出现了。我可以从 UI 中删除它,但在 firebase 中数据仍然存在。我已经完成了 coutless 研究,但无法找到与此特定问题相关的任何内容。

数据服务类

let DB_BASE = FIRDatabase.database().reference().child("laboratory")       //contains the root of our database
let STORAGE_BASE = FIRStorage.storage().reference()

class DataService 

static let ds = DataService()

//DB References
private var _REF_BASE = DB_BASE
private var _REF_STATION = DB_BASE.child("stations")
private var _REF_USERS = DB_BASE.child("users")

//Storage Reference
private var _REF_ITEM_IMAGE = STORAGE_BASE.child("item-pics")

var REF_BASE: FIRDatabaseReference 
    return _REF_BASE


var REF_STATION: FIRDatabaseReference 
    return _REF_STATION


var REF_USERS: FIRDatabaseReference 
    return _REF_USERS


var REF_ITEM_IMAGES: FIRStorageReference 
    return _REF_ITEM_IMAGE


//creating a new user into the firebase database

func createFirebaseDBUser(_ uid: String, userData: Dictionary<String, String>) 
    REF_USERS.child(uid).updateChildValues(userData)


库存视图控制器

import UIKit
import Firebase

class InventoryViewController: UIViewController, UITableViewDataSource,    UITableViewDelegate, UIImagePickerControllerDelegate,   UINavigationControllerDelegate 

var items = [Item]()

private var _station: Station!
private var _item: Item!

var sortIndex = 3

var imagePicker: UIImagePickerController!
static var imageCache: NSCache<NSString, UIImage> = NSCache()
var imageSelected = false

@IBOutlet weak var itemImageToAdd: UIImageView!
@IBOutlet weak var objectTextInput: UITextField!
@IBOutlet weak var brandTextInput: UITextField!
@IBOutlet weak var unitTextInput: UITextField!
@IBOutlet weak var amountTextInput: UITextField!
@IBOutlet weak var tableView: UITableView!
@IBOutlet var addItemView: UIView!
@IBOutlet weak var currentStationLabel: UILabel!

var station: Station 
    get 
        return _station
     set 
        _station = newValue
    


override func viewDidLoad() 
    super.viewDidLoad()

    var currentStationName = station.title

    currentStationLabel.text = currentStationName

    self.items = []

    let currentStation = station.title
    let stationRef = DataService.ds.REF_STATION.child(currentStation!)
    let inventoryRef = stationRef.child("inventory")

    tableView.delegate = self
    tableView.dataSource = self

    imagePicker = UIImagePickerController()
    imagePicker.allowsEditing = true
    imagePicker.delegate = self

    inventoryRef.observe(.value, with:  (snapshot) in
        print(snapshot.value!)

        self.items = []

        if let snapshot = snapshot.children.allObjects as? [FIRDataSnapshot] 

            for snap in snapshot 

                print("SNAP: \(snap)")
                if let itemDict = snap.value as? Dictionary<String, AnyObject> 

                    let key = snap.key
                    let item = Item(itemKey: key,
                                    itemData: itemDict)
                    self.items.append(item)
                
            
        
        self.tableView.reloadData()
    )




func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
    let item = items[indexPath.row]

    if let cell = tableView.dequeueReusableCell(withIdentifier: "inventoryTableCell", for: indexPath) as? ItemCell 

        if let img = InventoryViewController.imageCache.object(forKey: NSString(string: item.imageURL!)) 

            cell.updateItemUI(item: item, img: img)

         else 

            cell.updateItemUI(item: item)
        

        return cell

     else 

        return ItemCell()
    

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

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
    return items.count


func postToFirebase(itemImageURL: String) 

    let post: Dictionary<String, AnyObject> = [
        "objectLabel": objectTextInput.text! as AnyObject,
        "brandLabel": brandTextInput.text! as AnyObject,
        "unitLabel": unitTextInput.text! as AnyObject,
        "amountLabel": amountTextInput.text! as AnyObject,

        //post elsewhere as an image for future reference
        "itemImageURL": itemImageURL as AnyObject,

        ]
    let stationText = _station.title
    let stationRef = DataService.ds.REF_STATION.child(stationText!)
    let inventoryRef = stationRef.child("inventory")

    let firebasePost = inventoryRef.childByAutoId()
    firebasePost.setValue(post)

    objectTextInput.text = ""
    brandTextInput.text = ""
    unitTextInput.text = ""
    amountTextInput.text = ""
    imageSelected = false

    tableView.reloadData()


func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) 
    if let image = info[UIImagePickerControllerEditedImage] as? UIImage 

        itemImageToAdd.image = image
        imageSelected = true
     else 

        print("Please select a valid image")
    

    imagePicker.dismiss(animated: true, completion: nil)


@IBAction func backToStations(_ sender: Any) 

    performSegue(withIdentifier: "backToStations", sender: nil)



func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool 
    return true


func tableView(tableView: (UITableView!), commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: (NSIndexPath!)) 



func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? 

    let currentStation = station.title
    let stationRef = DataService.ds.REF_STATION.child(currentStation!)
    let inventoryRef = stationRef.child("inventory")

    var deleteAction = UITableViewRowAction(style: .default, title: "Delete") action in

        //Insert code to delete values from Firebase
        self.items.remove(at: indexPath.row)
        tableView.deleteRows(at: [indexPath as IndexPath], with: .fade)

    

    var editAction = UITableViewRowAction(style: .normal, title: "Edit")  action in

    

    return [deleteAction, editAction]
  

我的思考过程是在删除时调用 self_items.key 引用特定 tableCell 行的当前键。从那里我会使用当前的关键whick将是autoID并以这种方式删除值。不幸的是,这会使程序因致命的 nil 错误而崩溃。

【问题讨论】:

您在问题中包含了指向 JSON 树图片的链接。请将其替换为实际的 JSON 作为文本,您可以通过单击 Firebase 数据库控制台中的导出 JSON 链接轻松获取该文本。将 JSON 作为文本使其可搜索,让我们可以轻松地使用它来测试您的实际数据并在我们的答案中使用它,总的来说这只是一件好事。 How can I delete a specific child node in Firebase from UITableViewCell using Swift的可能重复 请看我对This Question的回复。这是一个不同的问题,但答案提供了适用于您的问题的设计模式。并且......在那张纸条上,如果您正在观察firebase中的节点以进行删除,那么您甚至不需要将它从您的阵列中删除。一旦您知道要删除哪个节点,删除该节点将通知您的应用程序,该应用程序将重新加载数组并相应地更新您的 tableView。 【参考方案1】:

我发现解决此问题的最佳方法是在您的删除操作中,从 Firebase 中删除对象。不要从这里更改 tableview。

然后在您的数据监听器中,检查数据何时返回为已删除(或 NULL),然后将其从 tableview 数据源数组中删除并更新 tableview。

【讨论】:

以上是关于如何在 Firebase 中显示 autoID 子项下的数据?的主要内容,如果未能解决你的问题,请参考以下文章

Firebase 实时规则如何检查具有 AutoID 的节点是不是包含正确的数据

如何在swift ui中使用autoid将带有字段的新文档添加到firebase集合

在 Firebase 中查询以下 AutoID

访问唯一 AutoID 中的 Firebase 数据

Firebase,Swift:仅检索那些具有特定键的“autoID”节点

AutoID 的 Swift Firebase 数据库数组