I am doing a call into a child "following" and am seeing if the logged-in user's UID is there and has a child of another user which the logged-in user is following.
I am printing who the logged-in user is following into a tableview. The first problem is my code, because I know it is bad practice to have two firebase calls within each other so I need someone to teach me a better method. Because of the poor code, when I go unfollow the other user and come back to the tab where the logged-in users list of who they are following is displayed it shows this (image below). When the logged-in user is following nobody it should just display the "Sorry!" text, yet still keeps who the user was following. Need someone to teach me a better method for doing this type of firebase call. Code and a firebase JSON stack image are below... In the firebase JSON stack image, the expanded UID is the logged-in user and the child in is the other user the logged-in user is following. I need a better way to call and extract this information, I am just ignorant of how-to.
func getFollowingData() {
Database.database().reference().child("following").child(uid!).observe(DataEventType.value, with: { (snapshot) in
if snapshot.exists() {
print("Got Snapshot")
Database.database().reference().child("following").child(self.uid!).observe(.childAdded, with: { (snapshot) in
if snapshot.exists() {
print(snapshot)
let snapshot = snapshot.value as? NSDictionary
self.listFollowing.append(snapshot)
self.followingTableView.insertRows(at: [IndexPath(row:self.listFollowing.count-1,section:0)], with: UITableViewRowAnimation.automatic)
self.followingTableView.backgroundView = nil
}
})
} else {
print("No Snapshot")
self.followingTableView.backgroundView = self.noDataView
}
})
}
Figured it out, just needed to do it how I did it before on other feeds.
import UIKit
import Firebase
class BusinessFollowing: UITableViewController {
#IBOutlet var noDataView: UIView!
#IBOutlet var followingTableView: UITableView!
var yourFollowing = [Information]()
var listFollowing = [NSDictionary?]()
var databaseRef = Database.database().reference()
let uid = Auth.auth().currentUser?.uid
var loggedInUser = Auth.auth().currentUser
var loggedInUserData:NSDictionary?
var following = [String]()
override func viewDidLoad() {
super.viewDidLoad()
self.followingTableView.backgroundView = nil
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.followingTableView.reloadData()
self.yourFollowing.removeAll()
self.following.removeAll()
getFollowingData()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
super.prepare(for: segue, sender: sender)
if segue.identifier == "following" {
// gotta check if we're currently searching
if let indexPath = followingTableView.indexPathForSelectedRow {
let user = listFollowing[indexPath.row]
let controller = segue.destination as? ExploreBusinessProfileSwitchView
controller?.otherUser = user
}
}
}
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 {
// #warning Incomplete implementation, return the number of rows
return self.yourFollowing.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! BusinessFollowingCell
let following = yourFollowing[indexPath.row]
let businessName = following.businessName
let businessStreet = following.businessStreet
let businessCity = following.businessCity
let businessState = following.businessState
cell.businessName.text = businessName
cell.businessStreet.text = businessStreet
cell.businessCity.text = businessCity
cell.businessState.text = businessState
// cell.businessName?.text = self.listFollowing[indexPath.row]?["businessName"] as? String
// cell.businessStreet?.text = self.listFollowing[indexPath.row]?["businessStreet"] as? String
// cell.businessCity?.text = self.listFollowing[indexPath.row]?["businessCity"] as? String
// cell.businessState?.text = self.listFollowing[indexPath.row]?["businessState"] as? String
return cell
}
func getFollowingData() {
self.yourFollowing.removeAll()
self.following.removeAll()
self.followingTableView.reloadData()
Database.database().reference().child("Businesses").child((loggedInUser?.uid)!).child("following").observe(.value, with: { snapshot in
if snapshot.exists() {
MBProgressHUD.showAdded(to: self.view, animated: true)
let databaseRef = Database.database().reference()
databaseRef.child("Businesses").queryOrderedByKey().observeSingleEvent(of: .value, with: { (usersSnapshot) in
let users = usersSnapshot.value as! [String: AnyObject]
for (_, value) in users {
if let userID = value["uid"] as? String {
if userID == Auth.auth().currentUser?.uid {
print(value)
if let followingUsers = value["following"] as? [String : String] {
for (_,user) in followingUsers {
self.following.append(user)
}
}
databaseRef.child("following").queryOrderedByKey().observeSingleEvent(of: .value, with: { (postsSnapshot) in
let posts = postsSnapshot.value as! [String: AnyObject]
for (_, post) in posts {
for (_, postInfo) in post as! [String: AnyObject] {
if let followingID = postInfo["uid"] as? String {
for each in self.following {
if each == followingID {
guard let uid = postInfo["uid"] as! String? else {return}
guard let name = postInfo["businessName"] as! String? else {return}
guard let address = postInfo["businessStreet"] as! String? else {return}
guard let state = postInfo["businessState"] as! String? else {return}
guard let city = postInfo["businessCity"] as! String? else {return}
self.yourFollowing.append(Information(uid: uid, businessName: name, businessStreet: address, businessCity: city, businessState: state))
}
self.followingTableView.backgroundView = nil
self.followingTableView.reloadData()
}
}
}
}
MBProgressHUD.hide(for: self.view, animated: true)
}) { (error) in
print(error.localizedDescription)
}
}
}
}
})
} else {
print("Not following anyone")
self.followingTableView.backgroundView = self.noDataView
MBProgressHUD.hide(for: self.view, animated: true)
}
})
}
}
Related
I'm trying to get a list of images from my firebase database. Inside the observe method, if I print the number of posts it works correctly. If I print the number of posts outside the observe function, but still inside the fetchPosts() function, I get 0. If I print the number of posts after the fetchPosts() call (the function that uses observe), I get 0.
How can I save the values to my dictionary posts inside of this async call? I've tried completion and dispatch groups. I might not have implemented them correctly so if you see an easy way to do it then please help me out. Here is the code:
import UIKit
import SwiftUI
import Firebase
import FirebaseUI
import SwiftKeychainWrapper
class FeedViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource{
#IBOutlet weak var collectionview: UICollectionView!
//var posts = [Post]()
var posts1 = [String](){
didSet{
collectionview.reloadData()
}
}
var following = [String]()
//var posts1 = [String]()
var userStorage: StorageReference!
var ref : DatabaseReference!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
fetchPosts()
}
// func lengthyTask(completionHandler: (Int) -> Int)
// {
// let result = completionHandler(42)
// print(result)
// }
//
// lengthyTask(completionHandler: { number in
// print(number)
// return 101
// })
//
func fetchPosts() {
let uid = Auth.auth().currentUser!.uid
let ref = Database.database().reference().child("posts")
let uids = Database.database().reference().child("users")
uids.observe(DataEventType.value, with: { (snapshot) in
let dict = snapshot.value as! [String:NSDictionary]
for (_,value) in dict {
if let uid = value["uid"] as? String{
self.following.append(uid)
}
}
ref.observe(DataEventType.value, with: { (snapshot2) in
let dict2 = snapshot2.value as! [String:NSDictionary]
for(key, value) in dict{
for uid2 in self.following{
if (uid2 == key){
for (key2,value2) in value as! [String:String]{
//print(key2 + "this is key2")
if(key2 == "urlToImage"){
let urlimage = value2
//print(urlimage)
self.posts1.append(urlimage)
self.collectionview.reloadData()
print(self.posts1.count)
}
}
}
}
}
})
self.collectionview.reloadData()
})
//ref.removeAllObservers()
//uids.removeAllObservers()
print("before return")
print(self.posts1.count)
//return self.posts1
}
func numberOfSections(in collectionView: UICollectionView) ->Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return posts1.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "PostCell", for: indexPath) as! PostCell
cell.postImage.sd_setImage(with: URL(string: posts1[indexPath.row]))
//creating the cell
//cell.postImage.downloadImage(from: self.posts[indexPath.row])
// let storageRef = Storage.storage().reference(forURL: self.posts[indexPath.row].pathToImage)
//
//
print("im trying")
//let stickitinme = URL(fileURLWithPath: posts1[0])
//cell.postImage.sd_setImage(with: stickitinme)
//cell.authorLabel.text = self.posts[indexPath.row].author
//cell.likeLabel.text = "\(self.posts[indexPath.row].likes) Likes"
return cell
}
#IBAction func signOutPressed(_sender: Any){
signOut()
self.performSegue(withIdentifier: "toSignIn", sender: nil)
}
#objc func signOut(){
KeychainWrapper.standard.removeObject(forKey:"uid")
do{
try Auth.auth().signOut()
} catch let signOutError as NSError{
print("Error signing out: %#", signOutError)
}
dismiss(animated: true, completion: nil)
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destination.
// Pass the selected object to the new view controller.
}
*/
}
You need only a few slightly changes
Declare posts1 simply
var posts1 = [String]()
and remove the property observer didSet
Delete the line self.collectionview.reloadData() right after self.posts1.append(..
Move the last occurrence of self.collectionview.reloadData() one level up, wrap it in a DispatchQueue block to update the collection view on the main thread and delete the print lines after the outer closure
}
DispatchQueue.main.async {
self.collectionview.reloadData()
}
})
})
}
And there is a typo in the second closure. It must be
let dict2 = snapshot2.value as! [String:NSDictionary]
for(key, value) in dict2 {
Variable names with trailing indices are pretty error-prone, better would be for example userDict and postDict
Edit :
This is the code with the order of execution
override func viewDidLoad() {
super.viewDidLoad()
collectionview.dataSource = self
collectionview.delegate = self
// 1
fetchPosts()
// 5
}
func fetchPosts() {
// 2
let uid = Auth.auth().currentUser!.uid
let ref = Database.database().reference().child("posts")
let uids = Database.database().reference().child("users")
// 3
uids.observe(DataEventType.value, with: { (snapshot) in
// 6
let dict = snapshot.value as! [String:NSDictionary]
for (_,value) in dict {
if let uid = value["uid"] as? String{
self.following.append(uid)
}
}
// 7
ref.observe(DataEventType.value, with: { (snapshot2) in
// 9
let dict2 = snapshot2.value as! [String:NSDictionary]
for(key, value) in dict2 { // TYPO!!!!
for uid2 in self.following{
if (uid2 == key){
for (key2,value2) in value as! [String:String]{
//print(key2 + "this is key2")
if(key2 == "urlToImage"){
let urlimage = value2
//print(urlimage)
self.posts1.append(urlimage)
print(self.posts1.count)
}
}
}
}
}
DispatchQueue.main.async {
// 11
self.collectionview.reloadData()
}
// 10
})
// 8
})
// 4
}
Im retrieve data from firebese and show in tableView
In tavleViewCell I have butons : like, unLike
when I press like need to hide likeButton and show UnlikeButton
And store/remove data from firebase
Now I create metods and when I click Like -> data save to firebase and show unlikeButton BUT unlikeButton shows in another cell's(not in all cells- example if I click in 0 indexPath.row, unlikeButton shows in 0,6,12,17..) Maybe this may happen when I scroll tableView
in cell I have :
protocol TableThemeQuote {
func likeTap(_ sender: ThemesQuoteCell)
func unlikeTap(_ sender: ThemesQuoteCell)
}
class ThemesQuoteCell: UITableViewCell {
#IBOutlet weak var likeBtn: UIButton!
#IBOutlet weak var unlikeBtn: UIButton!
var themeDelegate: TableThemeQuote?
var index: indexPath?
#IBAction func likeBtn(_ sender: UIButton) {
sender.tag = index.row
themeDelegate?.likeTap(self)
}
#IBAction func unLikeBtn(_ sender: UIButton) {
sender.tag = index.row
themeDelegate?.unlikeTap(self)
}
}
In ViewController:
var userMarks: [String] = [String]()
override func viewDidLoad() {
super.viewDidLoad()
likeLike()
}
func likeLike() {
let userUID = Auth.auth().currentUser!.uid
let ref = Database.database().reference().child("users").child("\(userUID)")
ref.observeSingleEvent(of: .value, with: { (snapshot) in
if let properties = snapshot.value as? [String : AnyObject] {
if let peopleWhoLike = properties["userLikes"] as? [String : AnyObject] {
self.likeLikeL.append(peopleWhoLike)
for (id,person) in peopleWhoLike {
self.userLikeCheck.updateValue(person, forKey: id)
self.userMarks.append(person as! String)
}
}
}
})
}
In cellForRowAt indexPath:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "themesQuoteCell") as! ThemesQuoteCell
let index = indexPath.row
cell.index = index
cell.themeDelegate = self
let mark = "Темы/\(themeName)/\(quotenumber[index.row])"
if userMarks.contains(mark){
if cell.likeBtn.tag == index.row {
cell.likeBtn.isHidden = true
cell.unlikeBtn.isHidden = false
break
}
}
return cell
}
In TableThemeQuote extension:
extension ThemeQuoteVC: TableThemeQuote {
func likeTap(_ sender: ThemesQuoteCell) {
guard let tappedIndexPath = themeQuoteTableView.indexPath(for: sender) else { return }
let ref = Database.database().reference().child("Темы").child("\(self.themeName)").child("\(quotenumber[tappedIndexPath.row])")
let keyToPost = ref.childByAutoId().key!
let updateLikes: [String : Any] = ["peopleWhoLike/\(keyToPost)" : Auth.auth().currentUser!.uid]
ref.updateChildValues(updateLikes, withCompletionBlock: { (error, reff) in
if error == nil {
ref.observeSingleEvent(of: .value, with: { (snap) in
if let properties = snap.value as? [String : AnyObject] {
if let likes = properties["peopleWhoLike"] as? [String : AnyObject] {
let count = likes.count
sender.likeLbl.text = "\(count)"
let update = ["quant" : count]
ref.updateChildValues(update)
sender.likeBtn.isHidden = true
sender.unlikeBtn.isHidden = false
sender.likeBtn.isEnabled = true
}
}
})
}
})
ref.removeAllObservers()
}
func unlikeTap(_ sender: ThemesQuoteCell) {
sender.unlikeBtn.isEnabled = false
guard let uid = Auth.auth().currentUser?.uid else { return }
let ref = Database.database().reference().child("users").child("\(uid)")
guard let tappedIndexPath = themeQuoteTableView.indexPath(for: sender) else { return }
let mark = "Темы/\(themeName)/\(quotenumber[tappedIndexPath.row])"
unlikeCellBtn(index: tappedIndexPath.row, sender: sender)
if sender.unlikeBtn.tag == tappedIndexPath.row {
ref.observeSingleEvent(of: .value, with: { (snapshot) in
if let properties = snapshot.value as? [String : AnyObject] {
if let peopleWhoLike = properties["userLikes"] as? [String : AnyObject] {
for (id,person) in peopleWhoLike {
if person as! String == mark {
ref.child("userLikes").child(id).removeValue(completionBlock: { (error, reff) in
if error == nil {
ref.observeSingleEvent(of: .value, with: { (snap) in
if let prop = snap.value as? [String : AnyObject] {
if let likes = prop["userLikes"] as? [String : AnyObject] {
let count = likes.count
ref.updateChildValues(["quantLikes" : count])
}else {
ref.updateChildValues(["quantLikes" : 0])
}
}
})
}
})
sender.likeBtn.isHidden = false
sender.unlikeBtn.isHidden = true
sender.unlikeBtn.isEnabled = true
break
}
}
}
}
})
}
ref.removeAllObservers()
}
What Im doing wrong and how can I get current tap and show/hide only that button which I press?
Cells are reused. This part of the code
if userMarks.contains(mark){
if cell.likeBtn.tag == index.row {
cell.likeBtn.isHidden = true
cell.unlikeBtn.isHidden = false
break
}
}
sets the hidden properties depending on some conditions but keeps the hidden state unchanged if the conditions are not met.
What you have to do is to add an else clause to set default values (by the way, the break statement is pointless)
if userMarks.contains(mark) && cell.likeBtn.tag == index.row {
cell.likeBtn.isHidden = true
cell.unlikeBtn.isHidden = false
} else {
cell.likeBtn.isHidden = <default value>
cell.unlikeBtn.isHidden = <default value>
}
I have a tableview that is being populated with who a user is following. Problem is that I need to pass that cells data to "var otherUser: NSDictionary!" but because I am populating the cell using a data structure file called "Information" I get this error - "Cannot assign value of type 'Information' to type 'NSDictionary?'" in the prepareForSegue. I am unsure if I can repackage the information I need into a NSDictionary so I can successfully do a data pass. I just don't know if this is a easy solution or an actual problem because of my ignorance.
Following TableViewController Code
import UIKit
import Firebase
class BusinessFollowing: UITableViewController {
#IBOutlet var noDataView: UIView!
#IBOutlet var followingTableView: UITableView!
var yourFollowing = [Information]()
var listFollowing = [NSDictionary?]()
var databaseRef = Database.database().reference()
let uid = Auth.auth().currentUser?.uid
var loggedInUser = Auth.auth().currentUser
var loggedInUserData:NSDictionary?
var following = [String]()
override func viewDidLoad() {
super.viewDidLoad()
self.followingTableView.backgroundView = nil
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.followingTableView.reloadData()
self.yourFollowing.removeAll()
self.following.removeAll()
getFollowingData()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
super.prepare(for: segue, sender: sender)
if segue.identifier == "following" {
// gotta check if we're currently searching
if let indexPath = followingTableView.indexPathForSelectedRow {
let user = self.yourFollowing[indexPath.row]
let controller = segue.destination as? ExploreBusinessProfileSwitchView
controller?.otherUser = user
}
}
}
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 {
// #warning Incomplete implementation, return the number of rows
return self.yourFollowing.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! BusinessFollowingCell
let following = yourFollowing[indexPath.row]
let businessName = following.businessName
let businessStreet = following.businessStreet
let businessCity = following.businessCity
let businessState = following.businessState
cell.businessName.text = businessName
cell.businessStreet.text = businessStreet
cell.businessCity.text = businessCity
cell.businessState.text = businessState
// cell.businessName?.text = self.listFollowing[indexPath.row]?["businessName"] as? String
// cell.businessStreet?.text = self.listFollowing[indexPath.row]?["businessStreet"] as? String
// cell.businessCity?.text = self.listFollowing[indexPath.row]?["businessCity"] as? String
// cell.businessState?.text = self.listFollowing[indexPath.row]?["businessState"] as? String
return cell
}
func getFollowingData() {
self.yourFollowing.removeAll()
self.following.removeAll()
self.followingTableView.reloadData()
Database.database().reference().child("Businesses").child((loggedInUser?.uid)!).child("following").observe(.value, with: { snapshot in
if snapshot.exists() {
MBProgressHUD.showAdded(to: self.view, animated: true)
let databaseRef = Database.database().reference()
databaseRef.child("Businesses").queryOrderedByKey().observeSingleEvent(of: .value, with: { (usersSnapshot) in
let users = usersSnapshot.value as! [String: AnyObject]
for (_, value) in users {
if let userID = value["uid"] as? String {
if userID == Auth.auth().currentUser?.uid {
print(value)
if let followingUsers = value["following"] as? [String : String] {
for (_,user) in followingUsers {
self.following.append(user)
}
}
databaseRef.child("following").queryOrderedByKey().observeSingleEvent(of: .value, with: { (postsSnapshot) in
let posts = postsSnapshot.value as! [String: AnyObject]
for (_, post) in posts {
for (_, postInfo) in post as! [String: AnyObject] {
if let followingID = postInfo["uid"] as? String {
for each in self.following {
if each == followingID {
guard let uid = postInfo["uid"] as! String? else {return}
guard let name = postInfo["businessName"] as! String? else {return}
guard let address = postInfo["businessStreet"] as! String? else {return}
guard let state = postInfo["businessState"] as! String? else {return}
guard let city = postInfo["businessCity"] as! String? else {return}
self.yourFollowing.append(Information(uid: uid, businessName: name, businessStreet: address, businessCity: city, businessState: state))
}
self.followingTableView.backgroundView = nil
self.followingTableView.reloadData()
}
}
}
}
MBProgressHUD.hide(for: self.view, animated: true)
}) { (error) in
print(error.localizedDescription)
}
}
}
}
})
} else {
print("Not following anyone")
self.followingTableView.backgroundView = self.noDataView
MBProgressHUD.hide(for: self.view, animated: true)
}
})
}
}
"Information" Data Structure File
import UIKit
class Information {
var uid: String
var businessName: String
var businessStreet: String
var businessCity: String
var businessState: String
init(uid: String, businessName: String, businessStreet: String, businessCity: String, businessState: String){
self.uid = uid
self.businessName = businessName
self.businessStreet = businessStreet
self.businessCity = businessCity
self.businessState = businessState
}
}
The error is pretty clear.
user in ExploreBusinessProfileSwitchView is obviously declared as NSDictionary, declare it as Information.
By the way don't use NSArray / NSDictionary in Swift. Use native types.
I have my firebase database structured like this:
Snap (-KWLSAIh5WJvNJOkxBEr) {
beschrijving = "description";
image = "link to image";
title = "title";
}
Snap (-KWLSTak0H20X_2Qnanv) {
beschrijving = "description";
image = "link to image";
title = "title";
}
This is the code I am using to display this in a TableView:
import UIKit
import Firebase
class NieuwsTableViewController: UITableViewController {
var users = [UsersII]()
let cellId = "IdCell"
override func viewDidLoad() {
super.viewDidLoad()
fetchUser()
}
func fetchUser() {
Database.database().reference().child("Blog").observe(.childAdded, with: { (snapshot) in
if let dictionary = snapshot.value as? [String: AnyObject] {
let user = UsersII(dictionary: dictionary)
self.users.append(user)
print(snapshot)
DispatchQueue.main.async(execute: {
self.tableView.reloadData()
})
}
}, withCancel: nil)
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return users.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> lllTableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath)
let user = users.reversed()[indexPath.row]
cell.textLabel?.text = user.name
return cell as! lllTableViewCell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let message = users.reversed()[indexPath.row]
guard let beschrijving = message.beschrijving else {
return
}
guard let image = message.plaatje else {
return
}
guard let titel = message.name else {
return
}
UserDefaults.standard.set(beschrijving, forKey: "nieuwsBeschrijving")
UserDefaults.standard.set(image,forKey: "nieuwsPlaatje")
UserDefaults.standard.set(titel, forKey: "nieuwsTitel")
self.performSegue(withIdentifier: "gotonews", sender: nil)
}
}
And I don't know if you will need this to answer this question but I'll also post the "UsersII" (defined as users just above the viewDidLoad method) in case this is needed to answer the question.
import UIKit
class UsersII: NSObject {
var name: String?
var beschrijving: String?
var plaatje: String?
init(dictionary: [String: Any]) {
self.name = dictionary["title"] as? String ?? ""
self.beschrijving = dictionary["beschrijving"] as? String ?? ""
self.plaatje = dictionary["image"] as? String ?? ""
}
}
so what I want to achieve is that if you click on one of the cells, you get the parent id of the article, so in this case that would be the "-KWLSAIh5WJvNJOkxBEr or -KWLSTak0H20X_2Qnanv" I mentioned above in my firebase database structure.
Here is what i was saying you to do:
Your model class:
class UsersII: NSObject {
var parentId: String?
var name: String?
var beschrijving: String?
var plaatje: String?
init(dictionary: [String: Any],parentId:String) {
self.name = dictionary["title"] as? String ?? ""
self.beschrijving = dictionary["beschrijving"] as? String ?? ""
self.plaatje = dictionary["image"] as? String ?? ""
self.parentId = parentId
}
}
Fetch user method:
func fetchUser() {
Database.database().reference().child("Blog").observe(.childAdded, with: { (snapshot) in
if let dictionary = snapshot.value as? [String: AnyObject] {
let user = UsersII(dictionary: dictionary,parentId:snapshot.key)
self.users.append(user)
print(snapshot)
DispatchQueue.main.async(execute: {
self.tableView.reloadData()
})
}
}, withCancel: nil)
}
And finaly you didSelect:
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let message = users.reversed()[indexPath.row]
guard let beschrijving = message.beschrijving else {
return
}
guard let image = message.plaatje else {
return
}
guard let titel = message.name else {
return
}
guard let parentId = message.name else
{
return
}
UserDefaults.standard.set(beschrijving, forKey: "nieuwsBeschrijving")
UserDefaults.standard.set(image,forKey: "nieuwsPlaatje")
UserDefaults.standard.set(titel, forKey: "nieuwsTitel")
UserDefaults.standard.set(parentId,forKey: "nieuwsParentId")
self.performSegue(withIdentifier: "gotonews", sender: nil)
}
}
I am a swift beginner,and I want to get value from firebase database,but it always recived twice same dictionary structure,and can't put value in tableview cells when I unwrapping it crashed...
here is my JSON format
Code work
import UIKit
import Firebase
//import FirebaseAuthUI
//import FirebaseGoogleAuthUI
//import FirebaseFacebookAuthUI
let device = FIRDatabase.database().reference()
class MainTableViewController: UITableViewController
{
var dic:NSDictionary?
override func viewDidLoad()
{
super.viewDidLoad()
//獲取當前登陸用戶
FIRAuth.auth()?.addStateDidChangeListener(self.UserAlive(auth:user:))
print("主畫面viewDidLoad")
}
func UserAlive(auth: FIRAuth, user: FIRUser?)
{
if user == nil
{
self.present((self.storyboard?.instantiateViewController(withIdentifier: "SignIn"))!, animated: true, completion: nil)
}
else
{
csGolbal.g_User = user
CheckData()
}
}
func CheckData()
{
print("CHECKDATA")
let ref = device.child("USER").child(csGolbal.g_User!.email!.replacingOccurrences(of: ".", with: "_"))
ref.observeSingleEvent(of: .value, with:
{ (snapshot) in
if snapshot.exists()
{
csGolbal.g_key = ((snapshot.value as AnyObject).allKeys)!
}
ref.child(csGolbal.g_key![0] as! String).observeSingleEvent(of: .value, with:
{ (snapshot) in
// Get user value
self.dic = snapshot.value as? NSDictionary
print(self.dic)
//self.tableView.reloadData()
})
})
}
and here is I don't get it how to put in
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
if let number = csGolbal.g_key?.count
{
return number
}
else
{
return 0
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCell(withIdentifier: "MainTableViewCell", for: indexPath) as! MainTableViewCell
//put in here
// label.text and ImageView
return cell
}
please hlep me,and tell me where I am do wrong.
#dahiya_boy I try your function
func getDataFromDB()
{
DispatchQueue.main.async( execute: {
//let dbstrPath : String! = "Firebase Db path"
let ref = device.child("USER").child(csGolbal.g_User!.email!.replacingOccurrences(of: ".", with: "_"))
ref.observeSingleEvent(of: .value, with: { (snapshot) in
if !snapshot.exists()
{
print("snapshot not exists")
}
else
{
for item in snapshot.children
{
let number = item as! FIRDataSnapshot
var aDictLocal : [String : String] = number.value! as! [String : String]
aDictLocal.updateValue(number.key, forKey: "key")
print("value \(number.value!) And Key \(number.key)") // Here you got data
}
}
self.tableView.reloadData()
})
})
}
and the result feedback twice
Actually you have stored Data in DB in random key so use below func
func getDataFromDB(){
DispatchQueue.main.async( execute: {
let dbstrPath : String! = "Firebase Db path)"
dbRef.child(dbstrPath!).observeSingleEvent(of: .value, with: { (snapshot) in
if !snapshot.exists(){
print("snapshot not exists")
}
else{
self.arrEmail.removeAll() // Add this
for item in snapshot.children {
let number = item as! FIRDataSnapshot
var aDictLocal : [String : String] = number.value! as! [String : String]
aDictLocal.updateValue(number.key, forKey: "key")
self.arrEmail.append(aDictLocal) // add this
print("value \(number.value!) And Key \(number.key)") // Here you got data
}
}
// self.tblContacts.reloadData()
})
})
}
Edit
Create one global array like below in your VC
var arrEmail = [[String : String]]() // Assuming your key and value all string
In the above code work add two lines (I edited and with comment add this)
self.arrEmail.removeAll()
and
self.arrEmail.append(aDictLocal) // Now in arrEmail you have all the values for every random key.