I cant see values from firebase swift - swift

Screen Shot 2019-04-01 at 4.45.08 PMenter image description hereI want to get the value from firebase that is stored I want to print it into a text label,
func fetchData(){
var ref: DatabaseReference!
ref = Database.database().reference()
guard let currentUid = Auth.auth().currentUser?.uid else {return}
Database.database().reference().child("users").child(currentUid).observeSingleEvent(of: .value, with: { (snapshot) in
guard let dictionary = snapshot.value as? Dictionary<String , AnyObject> else {return}
let uid = snapshot.value
let user = User(uid:uid as! String, dictionary: dictionary)
self.user = user
}) { (error) in
print(error.localizedDescription)
}
}
This is my another code to set the text label
func fetchData(){
var ref: DatabaseReference!
ref = Database.database().reference()
guard let currentUid = Auth.auth().currentUser?.uid else {return}
Database.database().reference().child("users").child(currentUid).observeSingleEvent(of: .value, with: { (snapshot) in
guard let dictionary = snapshot.value as? Dictionary<String , AnyObject> else {return}
let uid = snapshot.value
let user = User(uid:uid as! String, dictionary: dictionary)
self.userNameLabel.text = user.username
self.user = user
print(snapshot)
}) { (error) in
print(error.localizedDescription)
}
}
extra code to understand what I am doing
// user info stored
let userID = Auth.auth().currentUser?.uid
let userData = ["userName": userName,
"userAge ": userAge] as [String? : Any]
let values = [userID: userData]
let ref = Database.database().reference()
ref.child("users").childByAutoId().setValue(values)
}

I think you should use callbacks to communicate asynchronously with your controller.
In your example you get the uid by using "snpashot.value" but you should take the key of your dictionary instead.
Here is a similar example :
///Function that returns as callback the user stored in Firebase with a certain id.
func getUserFor(id: String, callback: #escaping (Bool, User?) -> Void) {
//Get the user in Firebase "user" collection with the specific id.
ref.child(Constants.userKey).child(id).observeSingleEvent(of: .value, with: { (userSnapshot) in
guard let userDictionnary = userSnapshot.value as? [String:Any] else { return callback(false, nil) }
let userId = userSnapshot.key
let userEmail = userDictionnary[Constants.emailKey] as? String
let user = User(id: userId, email: userEmail)
return callback(true, user)
}) { (error) in
print(error.localizedDescription)
return callback(false, nil)
}
}

I have found the answer I wasn't setting the user stored info in the firebase the right way.
let userID = Auth.auth().currentUser?.uid
let userData = ["userName": userName,
"userAge ": userAge] as [String? : Any]
let ref = Database.database().reference()
ref.child("users/\(userID ?? "")").setValue(userData)
}
//ref.child("users/(userID??"")").setValue(userData) // this was the error

Related

How to get the first name of the logged in User from firebase using Swiftui?

How to to get the first name of the current user which is logged in.
This is how my try looks like:
var ref: DatabaseReference!
ref = Database.database().reference()
let db = Firestore.firestore()
let userID = Auth.auth().currentUser?.uid
print(userID)
ref.child("users").child(userID!).observeSingleEvent(of: .value, with: { (snapshot) in
// Get user value
let value = snapshot.value as? NSDictionary
let username = value?["firstname"] as? String ?? ""
print(username)
// ...
}) { (error) in
print(error.localizedDescription)
}
Try the following:
let userId = Auth.auth().currentUser?.uid else { return }
let docRef = db.collection("users").document(userId)
docRef.getDocument(source: .cache) { (document, error) in
if let document = document {
let name = document.get("firstname")
print("Cached document data: \(name)")
} else {
print("Document does not exist in cache")
}
}
You are using cloud firestore but in your code, you are using the Realtime database. You need to check the following docs related to cloud firestore:
https://firebase.google.com/docs/firestore/quickstart

Swift - Remove key and values from dictionary [String : Any]

I am trying to removed block users from a dictionary [String : Any] that I am grabbing from the database. At first I grab the list of UID's that the current user has blocked:
var updatedBlockList: Any?
func findBlockUsers() {
// find current users list of blocked users
guard let currentUserUid = Auth.auth().currentUser?.uid else { return }
let blockedUsers = Database.database().reference().child("users").child(currentUserUid)
blockedUsers.observeSingleEvent(of: .value, with: { (snapshot) in
guard let userIdsDictionary = snapshot.value as? [String: Any] else { return }
userIdsDictionary.forEach({ (key, value) in
guard let userDictionary = value as? [String: Any] else { return }
var blockedList : Any
blockedList = userDictionary.keys
print(blockedList)
self.updateBlockList(blockedList: blockedList)
})
})
}
func updateBlockList(blockedList: Any) {
updatedBlockList = blockedList
print(updatedBlockList)
}
If I print updatedBlockList I get: ["gdqzOXPWaiaTn93YMJBEv51UUUn1", "RPwVj59w8pRFLf55VZ6LGX6G2ek2", "xmigo8CPzhNLlXN4oTHMpGo7f213"]
I now want to take those UID's (which will be the key in UserIdsDictionary and remove them after I pull ALL the users:
fileprivate func fetchAllUserIds() {
let ref = Database.database().reference().child("users")
ref.observeSingleEvent(of: .value, with: { (snapshot) in
guard let userIdsDictionary = snapshot.value as? [String: Any] else { return }
userIdsDictionary.forEach({ (key, value) in
// attempting to remove the blocked users here without any luck
var updatedKey = key as String?
updatedKey?.remove(at: self.updatedBlockList as! String.Index)
print(updatedKey!)
guard let userDictionary = value as? [String: Any] else { return }
let user = User(uid: key, dictionary: userDictionary)
self.fetchPostsWithUser(user: user)
})
}) { (err) in
print("Failed to fetch following user ids:", err)
}
}
I get this error when trying to remove: Could not cast value of type 'Swift.Dictionary.Keys' (0x1de2f6b78) to 'Swift.String.Index'
I'm sure i'm going about this the wrong way, but I know i'm close. The end goal is to take the blocked users UID's and remove them from the dictionary. Any help would be very much appreciated!!
Your forEach loop on userIdsDictionary is the wrong approach here so rather than trying to fix that code I would use a different approach and loop over the updatedBlockList
for item in updatedBlockList {
if let userID = item as? String {
userIdsDictionary.removeValue(forKey: userID)
}
}
For anyone wondering, here is the final changes that were made to make it work.
var updatedBlockList = [String]()
func findBlockUsers() {
// find current users list of blocked users
guard let currentUserUid = Auth.auth().currentUser?.uid else { return }
let blockedUsers = Database.database().reference().child("users").child(currentUserUid)
blockedUsers.observeSingleEvent(of: .value, with: { (snapshot) in
guard let userIdsDictionary = snapshot.value as? [String: Any] else { return }
userIdsDictionary.forEach({ (key, value) in
guard let userDictionary = value as? [String: Any] else { return }
let blockedList = Array(userDictionary.keys)
print(blockedList)
self.updateBlockList(blockedList: blockedList)
})
})
}
func updateBlockList(blockedList: [String]) {
updatedBlockList = blockedList
print(updatedBlockList)
}
fileprivate func fetchAllUserIds() {
let ref = Database.database().reference().child("users")
ref.observeSingleEvent(of: .value, with: { [weak self] (snapshot) in
guard var userIdsDictionary = snapshot.value as? [String: Any], let self = self else { return }
for item in self.updatedBlockList {
userIdsDictionary.removeValue(forKey: item)
}
userIdsDictionary.forEach({ (key, value) in
guard let userDictionary = value as? [String: Any] else { return }
let user = User(uid: key, dictionary: userDictionary)
self.fetchPostsWithUser(user: user)
})
}) { (err) in
print("Failed to fetch following user ids:", err)
}
}

Getting posts associated to specific user with Firebase and Swift

I have a piece of code that pulls all of the posts from my Firebase database. I'm trying to make the code pull all posts for a specific user id. The structure of my database is that user ids have a set of post ids associated to them.
The code that I have to pull all of the posts:
DataService.ds.REF_POSTS.observe(.value, with: { (snapshot) in
self.posts = []
if let snapshot = snapshot.children.allObjects as? [DataSnapshot] {
for snap in snapshot {
print("SNAP: \(snap)")
if let postDict = snap.value as? Dictionary<String, AnyObject> {
let key = snap.key
let post = Post(postKey: key, postData: postDict)
self.posts.append(post)
}
}
}
self.feedTableView.reloadData()
})
How I identify my current user:
_ = Auth.auth().addStateDidChangeListener { (auth,user) in
if let user = user {
let userId = user.uid
print("USER: \(String(describing: userId))")
let newPost = DataService.ds.REF_USERS.child("\(userId)").child("posts")
//print("NEW POST: \(newPost.child)")
newPost.setValue([userPost : true])
}
}
It looks like I need to get to the child (posts) of the users object and then cycle through the posts. How can I loop through (and observe for changes) the posts associated to the user that is signed in?
EDIT (Trying to cycle through all of a user's posts):
_ = Auth.auth().addStateDidChangeListener { (auth,user) in
if let user = user {
let userId = user.uid
print("USER: \(String(describing: userId))")
let newPost = DataService.ds.REF_USERS.child("\(userId)").child("posts")
newPost.observe(.value, with: { (snapshot) in
self.posts = []
if let snapshot = snapshot.children.allObjects as? [DataSnapshot] {
for snap in snapshot {
print("ERIC SNAP: \(String(describing: snap.value))")
if let postDict = snap.value as? Dictionary<String, AnyObject> {
let key = snap.key
let post = Post(postKey: key, postData: postDict)
self.posts.append(post)
}
}
}
self.feedTableView.reloadData()
})
//print("NEW POST: \(newPost)")
}
}
The way to get the signed in user's posts is done as follows:
guard let uid = Auth.auth().currentUser?.uid else {
return
}
print("USER ID: \(uid)")
let newPost = DataService.ds.REF_USERS.child("\(uid)").child("posts")
newPost.observe(.value, with: { (snapshot) in
self.posts = []
if let snapshot = snapshot.children.allObjects as? [DataSnapshot] {
for snap in snapshot {
let postData = DataService.ds.REF_POSTS.child(snap.key)
postData.observe(.value, with: { (snapshot) in
if let postDict = snapshot.value as? Dictionary<String, AnyObject> {
let key = snapshot.key
let post = Post(postKey: key, postData: postDict)
self.posts.append(post)
}
self.feedTableView.reloadData()
})
}
}
})

Problem while retrieving info from Firebase Database IOS

I'm trying to retrieve data from my Database but I'm having some problems, this is my database structure:
And here is my code
var ref : DatabaseReference
var idString = [String]()
ref = Database.database().reference()
ref.child("idUsers").observe(.value){ (snapshot) in
let id = snapshot.value as? String
if let ids = id {
idString.append(ids)
print(ids)
}
}
But no data is going into my array, I have been trying some solutions but no one works, please help! These are my rules by the way, they are public by default.
{
"rules": {
".read": true,
".write": true
}
}
Since idUsers contains multiple child nodes, you need to loop over the results in your code. Something like this:
ref.child("idUsers").observe(.value){ (snapshot) in
for userSnapshot in in snapshot.children.allObjects as? [DataSnapshot] {
let id = userSnapshot.value as? String
print(id)
idString.append(id)
}
print(ids)
}
**For creating database structure**
`override func viewDidLoad() {
var ref: DatabaseReference!
ref = Database.database().reference()
Auth.auth().createUser(withEmail: email, password: password) { authResult, error in
Auth.auth().signIn(withEmail: email, password: password) { [weak self] user, error in
guard self != nil else { return }
ref.child("users").setValue(["test1": "abc",
"test2": "efg",
"test3": "hij"])
}
}
}`
**// For retrieving data from firebase**
ref.observe(DataEventType.value, with: { (snapshot) in
let postDict = snapshot.value as? [String : AnyObject] ?? [:]
for item in postDict {
print(item)
}
})

Posts being loaded for all users in collection view firebase & swift

All I'm trying to do is fetch all the posts to the collection view that are within a certain radius of the current user. Currently I'm getting all the current users posts within the location but that is all. I can't figure out how to convert it to fetch all the posts from all the users.
FetchPostUserIds Is returning a snapshot of all the users and there UID
The geoFire query is only returning the postId from the current user. It shouldn't be I assume
Note: Updated Code
var PostKey: String?
var geoFire: GeoFire?
var regionQuery: GFRegionQuery?
var foundQuery: GFCircleQuery?
var geoFireRef: DatabaseReference!
override func viewDidLoad() {
super.viewDidLoad()
guard let uid = Auth.auth().currentUser?.uid else { return }
geoFireRef = Database.database().reference().child("posts").child(uid)
geoFire = GeoFire(firebaseRef: geoFireRef)
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let userLocation: CLLocation = locations[0] as CLLocation
let currentUserLocation = userLocation
let circleQuery = geoFire?.query(at: currentUserLocation, withRadius: 100.0)
_ = circleQuery?.observe(.keyEntered, with: { (key, location) in
self.PostKey = key
self.locationManager.stopUpdatingLocation()
})
}
fileprivate func fetchPostsWithUser(user: User) {
guard let key = PostKey else { return }
let ref = Database.database().reference().child("posts").child(user.uid).child(key)
ref.observeSingleEvent(of: .value, with: { (snapshot) in
self.collectionView?.refreshControl?.endRefreshing()
guard let dictionary = snapshot.value as? [String: Any] else { return }
var post = Post(user: user, dictionary: dictionary)
post.id = key
self.posts.append(post)
self.posts.sort(by: { (post1, post2) -> Bool in
return post1.creationDate.compare(post2.creationDate) == .orderedDescending
})
self.collectionView?.reloadData()
}) { (error) in
print(error)
}
}
fileprivate func fetchPostUserIds() {
let ref = Database.database().reference().child("users")
ref.observeSingleEvent(of: .value, with: { (snapshot) in
guard let userIdKey = snapshot.value as? [String: Any] else { return }
userIdKey.forEach({ (key, value) in
Database.fetchUserWithUID(uid: key, completion: { (user) in
self.fetchPostsWithUser(user: user)
})
})
}) { (error) in
print(error)
}
}
Try to debug and look what you got in the snapshot in your function, and also what fetchUserWithUID return
fileprivate func fetchPostUserIds() {
let ref = Database.database().reference().child("users")
ref.observeSingleEvent(of: .value, with: { (snapshot) in
guard let userIdKey = snapshot.value as? [String: Any] else { return }
userIdKey.forEach({ (key, value) in
Database.fetchUserWithUID(uid: key, completion: { (user) in
self.fetchPostsWithUser(user: user)
})
})
}) { (error) in
print(error)
}
}
Maybe with some more information I can help you
You pass paremeter user: User to method fetchPostsWithUser, but you always use the current user
guard let uid = Auth.auth().currentUser?.uid else { return }
also note these
let ref = Database.database().reference().child("users")
ref.observe(.value, with: { (snapshot) in
will load every change so think about singleObserve