简体   繁体   中英

Swift 4 / Firebase - Reading and storing double nested items from realtime databse in different arrays

I am really struggling with how to read and store my data from the firebase real-time database. This is what my database looks like:

text json
{
 "Live": {
    "Today": {
      "121321": {
        "title": "rnd",
        "description": "blah blah blah",
        "stamp": 1111
      },
      "121441": {
        "title": "arnd",
        "description": "blh blah blah",
        "stamp": 134
      }
    },
    "Tomorrow": {
      "143821": {
        "title": "brnd",
        "description": "blh blah blah",
        "stamp": 1134
      }
    },
    "ThisWeek": {
      "18934": {
        "title": "drnd",
        "description": "blh blh blah blah blah",
        "stamp": 237812
    },
      "323123": {
        "title": "crnd",
        "description": "blh blh blah blah",
        "stamp": 138921
     }
   }
  }
}

I have highlighted what I call events in green. Events have a title, description, and stamp. I then have an outer nest of today, tomorrow, and this week. Today, tomorrow, and this week are each separate dictionaries that hold any number of events.

I have created a class in a separate swift file:

class Event: NSObject {

    var EventTitle: String?
    var EventDescription: String?
    var EventStamp: Int?
    }

I want to have three arrays. The first array will have all events for "today", the second will have all events for "tomorrow" and the third will have all events for "this week". I will eventually need to sort the events in each array by stamp. However, I am stuck on how to convert the firebase datasnapshots into events and then put all events into an array. My code so far

//declaring empty arrays to fill later
    var todayEvents = [Event]()
    var tomorrowEvents = [Event]()
    var thisweekEvents = [Event]()

//Getting snapshots
ref?.child(".../LiveEvents").observeSingleEvent(of: .value, with: { (snapshot) in

     let todaysnap = snapshot.childSnapshot(forPath: "Today")
     let tomorrowsnap = snapshot.childSnapshot(forPath: "Tomorrow")
     let thisweeksnap = snapshot.childSnapshot(forPath: "ThisWeek")

     //need to assign data to events and to arrays Today, Tomorrow, Thisweek

     })

When I try to print my snap data I get an optional value and if I try to assign variable using as string then I get an error like "Cannot convert value of type 'DataSnapshot' to type 'Int' in coercion." I have looked at other answers, but I believe my situation is different since I have double nested data and I want to assign to different arrays. I'm using swift 4

Thank you

---If I do print(todaysnap) I get

Snap (Today) {
121321 =     {
    title = rnd;
    description = blah blah blah;
    stamp = 1111
};
121441 =     {
    title = arnd;
    description = blh blah blah;
    stamp = 134
};

} Doing print(todaysnap.value) gives me the same thing except the type is "Optional" instead of "Snap (Today)"

Here's the complete code to read all of the data in the Live node, and put Today, Tomorrow and ThisWeek events into separate array's

var todayArray = [String]()
var tomorrowArray = [String]()
var thisWeekArray = [String]()

let liveRef = self.ref.child("Live")
liveRef.observeSingleEvent(of: .value, with: { snapshot in

    let todaySnap = snapshot.childSnapshot(forPath: "Today")
    for todayChild in todaySnap.children {
        let todayChildSnap = todayChild as! DataSnapshot
        let todayDict = todayChildSnap.value as! [String: Any]
        let title = todayDict["title"] as! String
        todayArray.append(title)
    }

    let tomorrowSnap = snapshot.childSnapshot(forPath: "Tomorrow")
    for tomorrowChild in tomorrowSnap.children {
        let tomorrowChildSnap = tomorrowChild as! DataSnapshot
        let tomorrowDict = tomorrowChildSnap.value as! [String: Any]
        let title = tomorrowDict["title"] as! String
        tomorrowArray.append(title)
    }

    let thisWeekSnap = snapshot.childSnapshot(forPath: "ThisWeek")
    for thisWeekChild in thisWeekSnap.children {
        let thisWeekChildSnap = thisWeekChild as! DataSnapshot
        let thisWeekDict = thisWeekChildSnap.value as! [String: Any]
        let title = thisWeekDict["title"] as! String
        thisWeekArray.append(title)
    }

    print("Today")
    for today in todayArray {
        print("  " + today)
    }

    print("Tomorrow")
    for tomorrow in tomorrowArray {
        print("  " + tomorrow)
    }

    print("This Week")
    thisWeekArray.map { print("  " + $0) } //gettin' all swifty here
})

and the output is

Today
  rnd
  arnd
Tomorrow
  brnd
This Week
  drnd
  crnd

However... I would probably change the stucture:

Live
  event_0  //generated with childByAutoId
    title: "rnd"
    timestamp: "20180918"
  event_1
    title: "brnd"
    timestamp: "20180919"

because you can now query on every node, pulling out today's events. Tomorrow's events or ThisWeeks event or any day or range you like.

I'm going to uploading new data each day so today, tomorrow and this week will be refreshed each day

and with this structure, all you would need to do is add nodes and your queries will figure out what nodes are for what periods of time.

Since your Event class doesn't do any processing and essentially just a structure to hold your data, how about a struct:

struct EventStruct {
   var EventTitle: String?
   var EventDescription: String?
   var EventStamp: Int?
}

Then add the events to the array:

let title = thisWeekDict["title"] as! String
let desc = thisWeekDict["desc"] as! String
let stamp = thsWeekDict["stamp"] as! String
let anEvent = Event(title: title, desc: desc, stamp: stamp)
thisWeekArray.append(anEvent)

or leave it as a class and just pass the snapshot in and have the class assign the properties from the snapshot. Either way, please add error checking for nil's.

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