【问题标题】:Firebase Swift 3 Xcode 8 - iterate through observe resultsFirebase Swift 3 Xcode 8 - 遍历观察结果
【发布时间】:2017-04-20 05:36:35
【问题描述】:

我查看了 Firebase 上的文档以及 Stack Overflow 和 YouTube 教程,但如果通过 Firebase 获取数据,我可以了解如何获取数据。

我是 Firebase 的新手,并且正在将我的项目从 Parse 切换到 Firebase。

示例:我在 Firebase 中有一个如下所示的数据:

这样做我可以抓住 Swift 中的所有主题:

 let refDB  = FIRDatabase.database().reference(fromURL: firebaseDB_URL)
    let topicsRef = refDB.child("topics")
    // FIRDataSnapshot.
    topicsRef.observe(.value, with: { snapshot in
        for child in snapshot.children {
            print("child ------")
            print(child)
            // Get the bits  HOW DO I PARSE EACH SET

        }
    })

当我遍历 for 循环时,我会打印如下所示的内容:

child ------
Snap (-KYCqk2_AVkUd8s9cKit) {
    createdBy = FeMFeeDat4VZb5tmFO2tKixgQIy1;
    description = "Match states with their capitals";
    name = "State Caiptals";
    tags =     {
        0 = Geography;
        1 = USA;
    };
}

child ------
Snap (-KYCqk2_AVkUd8s9cKiu) {
    createdBy = FeMFeeDat4VZb5tmFO2tKixgQIy1;
    description = "Name the parts of an Atom";
    name = "Parts of an Antom";
    tags =     {
        0 = Physics;
        1 = Atom;
        2 = Electron;
    };
}

我的问题是,我如何获取数据:

我需要钥匙 (KYCqk2_AVkUd8s9cKiu) 我需要描述和名称 我需要一个标签数组

-- 全部在局部变量中?

基本上,我只想读入所有Topics 并在本地内存中有一个Topics 数组。

我可以负责构建 Class 主题的数组,但我尝试了几种方法来获取数据,但都没有运气。解析结果一定有一种简单的方法,但我没有找到示例或文档。

希望能提供一些帮助或指向一些文档或教程。

==================================

更新代码

您好,我更改了代码以尝试匹配提供的示例。代码现在如下所示 我放入了一个循环计数器以查看发生了什么以及为什么会崩溃。

FDataSnapshot 没有定义,所以我使用了 FIRDataSnapshot。

这是对现在崩溃的代码的新尝试。下面我将展示我的更改以使其不会崩溃 - 以及关于安全处理标签子节点的问题。感谢您的指点。我现在有一些有用的东西。

// HERE is a way to get all the Topics
let refDB  = FIRDatabase.database().reference(fromURL: firebaseDB_URL)
let topicsRef = refDB.child("topics")
// FIRDataSnapshot.
topicsRef.observe(.value, with: { snapshot in

    if snapshot.value is NSNull {
        print("not found")
    } else {
        var loopCount = 1  //  count loops to see how may time trying to loop
        for child in snapshot.children {

            print("            ")
            print("            ")
            print("child ------ loop \(loopCount)")
            print(child)

            let snap = child as! FIRDataSnapshot //each child is a snapshot
            let dict = snap.value as! [String: String] // the value is a dictionary
            let name = dict["name"]!
            let description = dict["description"]!
            let createdBy = dict["createdBy"]!
            print("the bits ------")
            print("name .... \(name)")
            print("description .... \(description)")
            print("createdBy .... \(createdBy)")
            loopCount += 1

        }
    }
})

我定义了零个断点——但是代码在这个断点处停止(当我确定定义了零个断点时)

libswiftCore.dylib`_swift_bridgeNonVerbatimFromObjectiveC:
    0x1144a4270 <+0>:   pushq  %rbp
    0x1144a4271 <+1>:   movq   %rsp, %rbp
    0x1144a4274 <+4>:   pushq  %r15

... 在此处中断 3 次,然后应用程序在此行崩溃 让 dict = snap.value 作为! [字符串:字符串] 带有消息“线程 1:EXC_BAD_INSTRUCTION (code=EXEC_1386_INVOP, subside=0x0)

我不确定为什么代码有断点以及为什么会崩溃。点击标签时可能会崩溃,因为标签是子节点并且不适合 [String, String]

我把这个打印在日志里然后就大功告成了!!!

child ------ loop 1
Snap (-KYI2MszjC9pK_4oIvKu) {
    createdBy = FeMFeeDat4VZb5tmFO2tKixgQIy1;
    description = "Match states with their capitals";
    name = "State Caiptals";
    tags =     {
        0 = Geography;
        1 = USA;
    };
}

=====

如果我将线路更改为使用“任何”......那么它可以工作

let dict = snap.value as! [String: Any]

新的工作代码 ....

// HERE is a way to get all the Topics
let refDB  = FIRDatabase.database().reference(fromURL: firebaseDB_URL)
let topicsRef = refDB.child("topics")
// FIRDataSnapshot.
topicsRef.observe(.value, with: { snapshot in

    if snapshot.value is NSNull {
        print("not found")
    } else {
        var loopCount = 1  //  count loops to see how may time trying to loop
        for child in snapshot.children {

            print("            ")
            print("            ")
            print("child ------ loop \(loopCount)")

            let snap = child as! FIRDataSnapshot //each child is a snapshot

            if snap.value != nil {
                print("key ... \(snap.key)")
                let dict = snap.value as! [String: Any] // the value is a dictionary
                let name = dict["name"] as! String
                let description = dict["description"] as! String
                let createdBy = dict["createdBy"] as! String
                let tags = dict["tags"] as! NSArray  

                /* Thought I could loop tags as! Dictionary but that does not work. Compiles but runtime crashes.
                var tagsArray = [String]()
                if tags != nil && tags.count > 0 {
                    for (key, value) in tags {
                        tagsArray.append(value)
                    }
                } */

                // Test to see what we got ...
                print("the bits ------")
                print("name .... \(name)")
                print("description .... \(description)")
                print("createdBy .... \(createdBy)")
                print("tags ... \(tags)  ... count \(tags.count)")
                loopCount += 1
            } else {
                print("bad snap")
            }

        }
    }
})

我从其他响应发送的文档链接中找出了主题键。谢谢。

我不确定我是否正确获取了标签值。它实际上只是一个字典,我试图以这种方式进行转换,但运行时崩溃并希望将标签转换为 NSArray .... 所以我在代码中这样做并且它有效但不确定这是否安全,因为这不是定义为数组,即使它作为数组返回。

【问题讨论】:

    标签: ios swift firebase firebase-realtime-database


    【解决方案1】:

    FIRDataSnapshot's value property 将快照的内容作为标准 Foundation 类型返回。

    【讨论】:

      【解决方案2】:

      真的都是关于字典的。

      给定一个示例节点

      people_foods
        -Yinasdjasjd
           name: "Leroy"
           food: "Pizza"
        -Yk9j9s9soks
           name: "Pete"
           food: "Wings"
      

      此代码将数据作为快照获取并对其进行迭代以打印人员及其食物。

          let ref = self.myRootRef.child(byAppendingPath: "people_foods")!
      
          ref.observe(.value, with: { snapshot in
      
              if ( snapshot!.value is NSNull ) {
                  print("not found")
              } else {
      
                  for child in (snapshot?.children)! {
      
                      let snap = child as! FDataSnapshot //each child is a snapshot
      
                      let dict = snap.value as! [String: String] // the value is a dict
      
                      let name = dict["name"]
                      let food = dict["food"]
      
                      print("\(name) loves \(food)")
                  }
      
              }
          })
      

      每个子节点的父节点名称也可以通过 child.key 找到。

      典型的设计模式是利用类数组(或字典或结构等)作为 tableView 的数据源。您将遍历孩子并为每个孩子创建一个类并将其附加到 tableView。完成后,tableView.reloadData 更新 UI。

      记住 Firebase 是异步的也很重要,因此在其中的代码完成之前,不要尝试在 Observe 闭包之外访问或使用该数组。

      【讨论】:

      • 我用有效的代码更新了原始问题。只是对安全处理“标签”子节点有疑问。
      【解决方案3】:

      您可以使用我的SnapshotParser 轻松做到这一点。

      您需要以下代码来获得快速表示:

      func main(){
          let topics=SnapshotParser().parseAsList(snap: Snapshot, type: Topic.self)
          for topic in topics{
              //do something with your object
          }
      }
      
      class Topic: ParsableSnapshot {
          var id:String?=nil
          var createdBy:String?=nil
          var description:String?=nil
          var name:String?=nil
          var tags:[Int:String]?=nil
      
          required init(){}
      
          func bindProperties(binder: SnapshotParser.Binder) {
              binder.bindField(name: "id", field: &id)
              binder.bindField(name: "createdBy", field: &createdBy)
              binder.bindField(name: "description", field: &description)
              binder.bindField(name: "name", field: &name)
              binder.bindDictionary(name: "tags", dict: &tags)
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-04-23
        • 1970-01-01
        • 2018-01-30
        • 2017-03-03
        • 1970-01-01
        • 2020-06-30
        • 2017-06-06
        • 2016-12-19
        相关资源
        最近更新 更多