D. Finna D. Finna - 15 days ago 8
Swift Question

Retrieving data from Firebase equals unexpected nil - swift

I get the weirdest error and I do not know how to fix it..
I have a Firebase database with all posts made from users. They are stored under

feed-items
. Whenever a user makes a new post, the post is added to
feed-items
and the key of the post in feed-items (an autoId) is added to every follower that the user has.

If I show all posts from
feed-items
in my UITableView then there is no problem at all. If I try to show posts that are equal to the keys stored in the users personal wall (the key that was added when users that I am following makes a post), then I get a weird error saying
unexpectedly found nil while unwrapping an optional
in my
Sweet
struct?

Let me first show you the two codes, one working the other is not:

WORKING CODE:

func observePosts(userID: String) {
// let ref = FIRDatabase.database().reference().child("Users").child(userID).child("Wall")
// ref.observeEventType(.ChildAdded, withBlock: { (snapshot) in
//
// let postId = snapshot.key
let postReference = FIRDatabase.database().reference().child("feed-items")//.child(postId)

postReference.observeSingleEventOfType(.Value, withBlock: { (snapshot) in
print(snapshot)
var newUpdates = [Sweet]()
for update in snapshot.children {
let postUpdates = Sweet(snapshot: update as! FIRDataSnapshot)
newUpdates.append(postUpdates)
}
self.updates = newUpdates.reverse()

dispatch_async(dispatch_get_main_queue(), {
self.tableView.reloadData()
})
}, withCancelBlock: nil)
//}, withCancelBlock: nil)
}


NOT WORKING CODE:

func observePosts(userID: String) {
let ref = FIRDatabase.database().reference().child("Users").child(userID).child("Wall")
ref.observeEventType(.ChildAdded, withBlock: { (snapshot) in

let postId = snapshot.key
let postReference = FIRDatabase.database().reference().child("feed-items").child(postId)

postReference.observeSingleEventOfType(.Value, withBlock: { (snapshot) in
print(snapshot)
var newUpdates = [Sweet]()
for update in snapshot.children {
let postUpdates = Sweet(snapshot: update as! FIRDataSnapshot)
newUpdates.append(postUpdates)
}

self.updates = newUpdates.reverse()

dispatch_async(dispatch_get_main_queue(), {
self.tableView.reloadData()
})
}, withCancelBlock: nil)
}, withCancelBlock: nil)
}


Where the app crashes and the line I get the error is in my struct, under likesForPost

MY STRUCT

import Foundation
import FirebaseDatabase
import FirebaseAuth
import UIKit

struct Sweet {
let key: String!
let content: String!
let addedByUser: String!
let profilePhoto: String!
var likesForPost : [String:AnyObject]
let itemRef: FIRDatabaseReference?
let path : String!
let date: String!
let category: Int!
let workoutComment: String!
let workoutTime: String!


init (content: String, addedByUser: String, profilePhoto: String!, likesForPost : [String:AnyObject]!, date: String, category: Int, workoutComment: String, workoutTime: String, key: String = "") {
self.key = key
self.content = content
self.addedByUser = addedByUser
self.profilePhoto = profilePhoto
self.likesForPost = likesForPost
self.itemRef = nil
// self.path = dataPath
self.path = ""
self.date = date
self.category = category
self.Comment = Comment
self.Time = Time
}

init (snapshot: FIRDataSnapshot) {
key = snapshot.key
itemRef = snapshot.ref
path = key
if let theFeedContent = snapshot.value!["content"] as? String {
content = theFeedContent
} else {
content = ""
}

if let feedUser = snapshot.value!["addedByUser"] as? String {
addedByUser = feedUser
} else {
addedByUser = ""
}

if let feedPhoto = snapshot.value!["profilePhoto"] as? String! {
profilePhoto = feedPhoto
} else {
profilePhoto = ""
}

if let feedLikes = snapshot.value!["likesForPost"] as? [String:AnyObject]! {
likesForPost = feedLikes
} else {
likesForPost = ["":""]
}

if let feedDate = snapshot.value!["date"] as? String! {
date = feedDate
} else {
date = ""
}

if let feedCategory = snapshot.value!["category"] as? Int! {
category = feedCategory
} else {
category = 0
}

if let feedComment = snapshot.value!["Comment"] as? String! {
Comment = feedComment
} else {
Comment = ""
}

if let feedTime = snapshot.value!["Time"] as? String! {
Time = feedTime
} else {
Time = ""
}

}

func toAnyObject() -> AnyObject {
return ["content":content, "addedByUser":addedByUser, "profilePhoto":profilePhoto!, "likesForPost":likesForPost, "date":date, "category":category, "Comment":Comment, "Time":Time]
}
}


I know it is a long post but I would be so happy if you took the time to help me - I am completely lost! :(

EDIT:
This is what the log is giving me:

Snap (-KXLGyWMljc2UNeRL1a3) {
addedByUser = "Maja P";
category = 1;
content = Hejehjehj;
date = "Nov,24,,2016,,1:20";
likesForPost = {
"user id" = 0;
};
profilePhoto = VGpbOweP4jO2seeLNCGiv1p08jq1;
Comment = "";
Time = "";
}
fatal error: unexpectedly found nil while unwrapping an Optional value


Which is completely correct, but there are two posts where it is only printing the one above.

Answer

Since in the second code you are directly getting DataSnapshot of your Post, I don't think you need to iterate the snapshot.

Try changing your code to this, see if it works.

func observePosts(userID: String) {
    let ref = FIRDatabase.database().reference().child("Users").child(userID).child("Wall")
    ref.observeEventType(.ChildAdded, withBlock: { (snapshot) in

        let postId = snapshot.key
        let postReference = FIRDatabase.database().reference().child("feed-items").child(postId)

        postReference.observeSingleEventOfType(.Value, withBlock: { (snapshot) in
            print(snapshot)
                let update = Sweet(snapshot: snapshot)
                self.updates.insert(update, atIndex: 0)

                dispatch_async(dispatch_get_main_queue(), {
                   self.tableView.reloadData()
                })

            }, withCancelBlock: nil)

        }, withCancelBlock: nil)
}