Filtering data snapshot Swift Firebase - swift

I'm trying to return data from the database which I've done successfully. The problem is I don't want all data to be featured, but only the ones with the current UID which is stored in the JSON tree.
Here is my JSON tree, there is only one current UID but there will be many.
user_posts-
LDLc60j71FBvJGeYn5i
description: "Write here"
photoUrl: "https://firebasestorage.googleapis.com/v0/b/blo..."
uid: "zQRxvM3cwzQMewUtVamk8JQrEFJ3"
Here is my current code returning all data from database folder:
var posts2 = [user_posts]()
func loadPosts(){
Database.database().reference().child("user_posts").observe(.childAdded) {(snapshot: DataSnapshot) in
if let dict = snapshot.value as? [String: Any] {
let descriptionText = dict["description"] as! String
let photoUrlString = dict["photoUrl"] as! String
let post = user_posts(descriptionText: descriptionText, photoUrlString: photoUrlString)
self.posts2.append(post)
self.myPageTableView.reloadData()
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
self.hideKeyboardWhenTappedAround()
myPageTableView.dataSource = self
myPageTableView.delegate = self
loadPosts()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return posts2.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCell(withIdentifier:"myPageCell", for: indexPath)
as! myPageTableViewCell
cell.myPageDescription?.text = posts2[indexPath.row].description
let photoUrl = posts2[indexPath.row].photoUrl
let url = URL(string: photoUrl)
cell.myPageImage.sd_setImage(with: url, placeholderImage: nil)
return cell
}
}

To load only the posts for a specific user, you'll want to use a Firebase query:
let uid = Auth.auth().currentUser.uid
let posts = Database.database().reference().child("user_posts")
let query = posts.queryOrdered(byChild: "").queryEqual(toValue: uid)
query.observe(.childAdded) {(snapshot: DataSnapshot) in
...
Also see the Firebase documentation on ordering and filtering data.

Related

Issue with TableView and Firebase implementation (Swift)

I want to connect my TableView to what I query from Firestore. The query works, but I can't get the TableView to show the content. Right now its just a blank tableView. The TableViewCell file also has no issues, since it worked before without the firebase implementation (The Cell is registered correctly).
I suspect that the issue is in cellForRowAt and tried played around in there, but couldn't get anything to work.
Can you find the issue?
import UIKit
import Firebase
class popularViewController: UIViewController, UITableViewDelegate, UITableViewDataSource{
#IBOutlet var table: UITableView!
var texttt = [TextPost]()
override func viewDidLoad() {
super.viewDidLoad()
gettingPosts()
table.register(textTableViewCell.nib(), forCellReuseIdentifier: textTableViewCell.identifier)
table.delegate = self
table.dataSource = self
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(true)
gettingPosts()
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let alle = models.count + texttt.count
return alle
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: textTableViewCell.identifier, for: indexPath) as! textTableViewCell
cell.configure(with: texttt[indexPath.row])
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 300
}
func gettingPosts(){
let db = Firestore.firestore()
let postsRef = db.collection("posts")
postsRef.addSnapshotListener { (querySnapshot, error) in
guard let snapshot = querySnapshot else {
print("Error fetching snapshots: \(error!)")
return
}
snapshot.documentChanges.forEach { diff in
if (diff.type == .added){
let data = diff.document.data()
let Name = data["username"] as! String
let text = data["description"] as! String
let likes = data["likes"] as! Int
let typ = data["postType"] as! Int
let pfp = data["profileImage"] as! String
let uid = data["uid"] as! String
let pic = data["picture"]
let time = data["time"] as! String
if typ == 0{ // Text post
let dasDing = TextPost(numberOfComments: 0, username: Name, timestampName: time, userImageName: pfp, textName: text)
self.texttt.append(dasDing)
}
}
}
}
}
}
struct TextPost {
let numberOfComments: Int
let username: String
let timestampName: String
let userImageName: String
let textName: String
}
You need to reload data once you get data from firebase
func gettingPosts(){
let db = Firestore.firestore()
let postsRef = db.collection("posts")
postsRef.addSnapshotListener { (querySnapshot, error) in
guard let snapshot = querySnapshot else {
print("Error fetching snapshots: \(error!)")
return
}
snapshot.documentChanges.forEach { diff in
if (diff.type == .added){
let data = diff.document.data()
let Name = data["username"] as! String
let text = data["description"] as! String
let likes = data["likes"] as! Int
let typ = data["postType"] as! Int
let pfp = data["profileImage"] as! String
let uid = data["uid"] as! String
let pic = data["picture"]
let time = data["time"] as! String
if typ == 0{ // Text post
let dasDing = TextPost(numberOfComments: 0, username: Name, timestampName: time, userImageName: pfp, textName: text)
self.texttt.append(dasDing)
}
}
}
DispatchQueue.main.async {
tableView.reloadData()
}
}
}

Firebase observe new added data even when the function isn't called

I have a function that observes data from my Firebase database. This data will be inserted in an array, so it can be send to my tableviewcell Viewcontroller. All the data will be put correct in the tabelviewcell, but I have a problem when I update my Firebase database. Everytime I change a value in the database it will immediately update my tableView even when my function is not called. I am not sure what I am doing wrong and how to prevent this.
This is my function observe:
Database.database().reference().child("posts").child("\(postId)").child("comments").observe(.value, with: { snapshot in
if let snapshots = snapshot.children.allObjects as? [DataSnapshot] {
for snap in snapshots {
if let postDict = snap.value as? Dictionary<String, AnyObject> {
let key = snap.key
let post = Comment.transformComment(dict: postDict)
self.comments.insert(post, at: 0)
self.tableView.reloadData()
}
}
}
})
Array:
var comments: [Comment] = []
extension Comment {
static func transformComment(dict: [String: Any]) -> Comment {
let comment = Comment()
comment.commentText = dict["commentText"] as? String
comment.uid = dict["uid"] as? String
comment.timestamp = dict["timestamp"] as? Int
comment.likeCount = dict["likeCount"] as? Int
comment.childByAutoId = dict["childByAutoId"] as? String
comment.id = dict["postId"] as? String
return comment
}
}
Tablevieww Functions:
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if comments.count == 0 {
self.tableView.setEmptyMessage("No comments yet!")
} else {
self.tableView.restore()
}
return comments.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Comment", for: indexPath) as! CommentTableViewCell
let comment = comments[indexPath.row]
cell.comment = comment
cell.delegate = self
return cell
}
To listen once replace
.child("comments").observe(.value, with: { snapshot in
With
.child("comments").observeSingleEvent(of: .value) { snapshot in
Or
.child("comments").observe(.childChanged) { snapshot in
to listen to added childs

Firebase tableview not populating, Swift

I have data in my db and can search for an individual record, that's working fine. But when I try to simply populate a tableview with all of the db records its not receiving/displaying any data.
here is my code:
struct drinkStruct {
let pub: String!
let rating: String!
let price: String!
}
override func viewDidLoad() {
super.viewDidLoad()
loadDrinks()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
#IBAction func homeClicked(_ sender: Any) {
homeClicked()
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return posts.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
let label1 = cell.viewWithTag(1) as! UILabel
label1.text = posts[indexPath.row].pub
let label2 = cell.viewWithTag(2) as! UILabel
label2.text = posts[indexPath.row].rating
let label3 = cell.viewWithTag(3) as! UILabel
label3.text = posts[indexPath.row].price
return cell
}
func loadDrinks(){
let databaseRef = Database.database().reference().child("Drinks")
ref = Database.database().reference()
databaseRef.queryOrderedByKey().observe(.childAdded, with: { (snapshot) in
if let valueDictionary = snapshot.value as? [AnyHashable:String]
{
let pub = valueDictionary["pub"]
let rating = valueDictionary["rating"]
let price = valueDictionary["price"]
self.posts.insert(drinkStruct(pub: pub, rating: rating, price: price), at: 0)
}
})
self.tableview.reloadData()
}
And here is my db structure:
Am I doing something blatantly obviously wrong? Or can anyone see what's causing no data to load?
There are no errors/unused variables etc etc.
Thanks in advance!
I think the following should do the job.
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
override func viewDidLoad() {
super.viewDidLoad()
//getting a reference to the node //
databaseRef = Database.database().reference().child("Drinks")
//observing the data changes
databaseRef.observe(DataEventType.value, with: { (snapshot) in
if snapshot.childrenCount > 0 {
// clearing the list //
self.posts.removeAll()
// iterating through all the values //
for drinks in snapshot.children.allObjects as! [DataSnapshot] {
let drinkObject = drinks.value as! [String: AnyObject]
let drinkPub = drinkObject["pub"]
let drinkRating = drinkObject["rating"]
let drinkPrice = drinkObject["price"]
//creating a drinkStruct object with the model //
let drinkModel = drinkStruct(pub: drinkPub as! String?, rating: drinkRating as! String?, price: drinkPrice as! String?)
//appending it to list
self.posts.append(drinkModel)
}
// reloading data //
self.tableView.reloadData()
}
})
}
var posts = [drinkStruct]()
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return posts.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! YourCustomTableViewCell
let drink: drinkStruct
drink = posts[indexPath.row]
cell.label1.text = drink.pub
cell.label2.text = drink.rating
cell.label3.text = drink.price
return cell
}
}
For the newbie that's here in my footsteps, I solved this by doing a lot of things.
You need to create the tableview & cell layout in the storyboard. Then you need a cell class that dictates/assigns what's happening in each cell(imageviews, labels etc) as well as a model class for whatever you're looking up, whatever the object may be.
This is the code I used for my function in which I populate the info in the cells with the data from Firebase:
func loadDrinks(){
Database.database().reference().child("Drinks").observe(.childAdded) { (snapshot: DataSnapshot) in
if let dict = snapshot.value as? [String: Any] {
let pub = dict["pub"] as! String
let rating = dict["rating"] as! String
let price = dict["price"] as! String
let drink = Drink(pub: pub.capitalized, rating: rating.capitalized, price: price.capitalized)
self.drinks.append(drink)
print(self.drinks)
self.tableview.reloadData()
}
}
}
This was a Newbie 101 question - my bad.

Core Data prints saved data but not showing up on table viewcontroller

I would like to show my saved data in core data on a table view controller, the data is saved properly and prints out the details on the console but the data is noot showing up on the tableview cell, kindly please help
var charData = [SavedCharacters]()
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
var name = String()
var house = String()
var ancestry = String()
var getImage = UIImage()
override func viewDidLoad() {
super.viewDidLoad()
getData()
}
func getData(){
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "SavedCharacters")
request.returnsObjectsAsFaults = false
do{
let result = try? context.fetch(request)
for data in result as! [NSManagedObject]
{
name = data.value(forKey: "name") as! String
print(data.value(forKey: "name")as! String)
}
}
tableView.reloadData()
}
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return charData.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "dataCell", for: indexPath) as! SavedDataTableViewCell
cell.nameLabel.text = charData[indexPath.row].name!
cell.house = charData[indexPath.row].house!
cell.ancestry = charData[indexPath.row].ancestry!
// displaying image in table view cell
if let imageURL = URL(string: self.charData[indexPath.row].image!) {
DispatchQueue.global().async {
let data = try? Data(contentsOf: imageURL)
if let data = data {
let image = UIImage(data: data)
DispatchQueue.main.async {
cell.charImageView.image = image
}
}
}
}
return cell
}
Definitely you've forgotten to init charData in getData() method
var charData: [CharData]
func getData(){
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "SavedCharacters")
request.returnsObjectsAsFaults = false
====> charData = []
do{
let result = try? context.fetch(request)
for data in result as! [CharData]
{
name = data.value(forKey: "name") as! String
print(data.value(forKey: "name")as! String)
===> charData.append(data)
}
}
tableView.reloadData()
}

Swift, Accessing data for a table view

So, I load my firebase node, and then append the data into an array to use in a table view, but for some reason i cannot access the data inside of planitTitles, unless i am within this closure. Please, any workaround ? I feel like i have achieved this before. Thanks
func loadFirebase(){
let ref = Database.database().reference()
let planits = ref.child("planits")
planits.observe( .value, with: { (planitsSnapshot) in
for child in planitsSnapshot.children {
let planSnap = child as! DataSnapshot
let planDict = planSnap.value as! [String: Any]
if self.keyForThisPlanit.contains(planSnap.key){
let title = planDict["Planit Title"] as! String
self.planitTitles.append(title)
}
}
})
print(self.planitTitles)
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "friendUpdatesCell") as? ViewUpdatesTVCell else { return UITableViewCell() }
cell.randomPlanitNumber.text = planitTitles[indexPath.row]
// CRASHES HERE WITH ERROR OUT OF INDEX
return cell
}
You need to reload the table after the for loop
var planitTitles = [String]()
//
func loadFirebase(){
let ref = Database.database().reference()
let planits = ref.child("planits")
planits.observe( .value, with: { (planitsSnapshot) in
self.planitTitles.removeAll() // you may want to clear here to avoid duplications
for child in planitsSnapshot.children {
let planSnap = child as! DataSnapshot
let planDict = planSnap.value as! [String: Any]
if self.keyForThisPlanit.contains(planSnap.key){
let title = planDict["Planit Title"] as! String
self.planitTitles.append(title)
}
}
print(self.planitTitles)
self.tableView.reloadData()
})
}
func numberOfRows(inSection section: Int) -> Int {
return planitTitles.count // to prevent cellForRowAt indexOutOfBounds crash
}