I want to make a user query, removing the name of each, and go keeping the names in an array, then display them on a table. The problem is I can not keep them in the settlement, how can I fix it? Thus I make the query to extract the names of users:
var users = [String]()
let ref = Firebase(url:"https:mydatabase/users")
ref.queryOrderedByChild("name").observeEventType(.ChildAdded,
withBlock: { snapshot in
if let username = snapshot.value["name"] as! String {
self.users.append(username)
print("username")
}
})
So I have my users table in firebase
The username var does have the name, but when adding the content of the var the settlement, does not, at the time of execution of the application does not throw any errors.
There are just a few typo's your code
Try this:
let usersRef = self.myRootRef.childByAppendingPath("users")
usersRef.queryOrderedByChild("name").observeEventType(.ChildAdded, withBlock: { snapshot in
if let username = snapshot.value["name"] as? String {
self.userArray.append(username)
print("\(username)")
}
})
Be sure to define the userArray as a property of the class so it will be available to other functions.
class MyClass: NSObject {
let myRootRef = Firebase(url:"https://your-app.firebaseio.com")
var userArray = [String]()
Related
I am having a hard time pulling all my data from one of my nodes in my firebase database.
Here is how the node looks like in Firebase:
Considerations
-MEdUNZwVrsDW3dTrE6N
Company Description:
Company Image:
Company Name:
Decision Date:
Start Date:
Users
B2Z4DlZ8RucvEQhz2NSUkquqc5P2
Compensation:
PostNumber:
StoryNumber:
Under users there are going to be multiple people with different values for the compensation, post number, and storynumber. I have each user having a node called "user-considerations" that tags the unique id of the consideration each user is attached on and places it under their UID and tags a 1 next to it as the value. I am trying to access each specific user's info along with the other info in the node. Here is my code that I am using to call the information along with the struct I a using to capture the information:
STRUCT:
import UIKit
class ConsiderationInfo: NSObject {
var companyName: String?
var companyImage: String?
var companyDescription: String?
var decisionDate: String?
var startDate: String?
var compensation: String?
var postNumber: String?
var storyNumber: String?
}
CODE FOR OBSERVING INFO:
func updateConsiderationsArray() {
let uid = Auth.auth().currentUser?.uid
let ref = Database.database().reference().child("user-considerations").child(uid!)
ref.observe(.childAdded, with: { (snapshot) in
let considerationId = snapshot.key
let considerationReference = Database.database().reference().child("Considerations").child(considerationId)
considerationReference.observe(.value, with: { (snapshot) in
if let dictionary = snapshot.value as? [String: AnyObject] {
let considerationInfo = ConsiderationInfo()
//self.setValuesForKeys(dictionary)
considerationInfo.companyName = dictionary["Company Name"] as? String
considerationInfo.companyImage = dictionary["Company Image"] as? String
considerationInfo.companyDescription = dictionary["Company Description"] as? String
considerationInfo.decisionDate = dictionary["Decision Date"] as? String
considerationInfo.startDate = dictionary["Start Date"] as? String
self.considerationsInfo.append(considerationInfo)
self.considerationName.append(considerationInfo.companyName!)
self.filteredConsiderations.append(considerationInfo.companyName!)
self.considerationCollectionView.reloadData()
}
}, withCancel: nil)
})
}
I am trying to access the information under the user specific node, i.e. the specific user's compensation post number and story number. I am unaware of how to access all of this to append the struct.
Here is the node with the user-considerations:
As it sits, I am really not seeing anything super wrong with the code but there are few things that could be changed to make it more streamlined.
I would first change the Consideration Info class to make it more self contained. Add a convenience initializer to handle a firebase snapshot directly with some error checking.
class ConsiderationInfo: NSObject {
var companyName = ""
convenience init(withSnapshot: DataSnapshot) {
self.init()
self.companyName = withSnapshot.childSnapshot(forPath: "Company Name").value as? String ?? "No Company Name"
}
}
I would also suggest removing the .childAdded and .observe events unless you specifically want to be notified of future changes. Use .value and .observeSingleEvent instead. Keeping in mind that .childAdded iterates over each node in your database one at a time - .value reads them in all at the same time. If there is a limited amount of data, .value works well.
func updateConsiderationsArray() {
let fbRef = Database.database().reference()
let uid = Auth.auth().currentUser?.uid
let ref = fbRef.child("user_considerations").child(uid)
ref.observeSingleEvent(of: .value, with: { snapshot in
let allUidsSnap = snapshot.children.allObjects as! [DataSnapshot]
for uidSnap in allUidsSnap {
let considerationId = uidSnap.key
let considerationReference = fbRef.child("Considerations").child(considerationId)
considerationReference.observeSingleEvent(of: .value, with: { snapshot in
let considerationInfo = ConsiderationInfo(withSnapshot: snapshot)
self.considerationArray.append(considerationInfo)
// update your collectionView
})
}
})
}
What I am doing in the above is reading in the single node from user_considerations, which looks like this according to your quuestion
user_considerations
some_user_uid
a_user_uid
a_user_uid
and then mapping each child user to an array to maintain order
let allUidsSnap = snapshot.children.allObjects as! [DataSnapshot]
and then iterating over each, getting the uid (the key) of each node and getting that nodes data from the Considerations node.
I am trying to create a view controller displaying information of the clicked shop from a UITableView on the previous view controller. However, I cannot retrieve data in the new view controller and I don't know how to solve this issue. Here is my database structure. Thank you for the help.
import UIKit
import Firebase
import FirebaseDatabase
class ShopViewController: UIViewController {
var name :String? // This is the name of the cell clicked on the previous viewcontroller
var ref: DatabaseReference!
#IBOutlet weak var shopName: UILabel!
#IBOutlet weak var shopType: UILabel!
#IBOutlet weak var imageView: UIImageView!
override func viewDidLoad() {
shopName.text = name
let ref = Database.database().reference().child("shops").childByAutoId().child(name!).child("Details")
ref.observe(.childAdded, with: { snapshot in
let snapshotValue = snapshot.value as! NSDictionary
let imageUrlString = snapshotValue["imageURL"] as! String
print(imageUrlString)
let shoptype = snapshotValue["type"] as! String
self.shopType.text = shoptype
})
}
}
The reference that you have is wrong, childByAutoId() is used to generate a unique id in your database.
Also the id that you currently have is the userid, you need to retrieve the userid:
let user = Auth.auth().currentUser
let uid = user.uid
then the location should be:
let ref = Database.database().reference().child("shops").child(uid).child("Eat").child("Details")
So there's a couple of issues here, first off is your data structure.
Something along these lines would be much easier to read from. You shouldn't need the name field as far as I can tell, and is there a requirement to have the details nested?
Reading the data
Next up, you can refactor your data reference code. I'd firstly recommend extracting the logic into its own method rather than having it directly in viewDidLoad:
var ref: DatabaseReference!
override func viewDidLoad() {
shopName.text = name
self.ref = Database.database().reference()
getShopDetails()
}
func getShopDetails() {
guard let shopName = name else { return }
ref.child("shops").child(shopName).observe(.childAdded, with: { snapshot in
guard let shop = snapshot.value as? [String: AnyObject] else { return }
let imageUrlString = shop["imageURL"] as! String
print(imageUrlString)
let shoptype = shop["type"] as! String
self.shopType.text = shoptype
})
}
I've modified to set the database reference value as otherwise this would crash if you tried to use it elsewhere. I've also added a couple of guard statements to minimise the number of explicit unwraps.
I can't comment on your list code, but have you considered doing the call for all of the shops in this, and mapping the result to a data object, which you can then use to display the data in the screen we're detailing here, rather than doing a separate query every-time you open a detail screen.
I am working with the following Firebase Database:
I add new chatIDs with the following code:
DatabaseReference.users(uid: self.uid).reference().child("chatIds/\(chat.uid)").setValue(chat.uid)
I need to add a single child to the individual "chatIDs" that is a random string that I will generate but I haven't worked with Firebase for that long so I am not sure how to do add children this far in. How can I write the code to do this?
Based on your database structure, a possible implementation of you want would be:
let ref = Database.database().reference()
// Generating the chat id
let refChats = ref.child("chats")
let refChat = refChats.childByAutoId()
// Accessing the "chatIds branch" from a user based on
// his id
let currentUserId = self.uid
let refUsers = ref.child("users")
let refUser = refUsers.child(currentUserId)
let refUserChatIds = refUser.child("chatIds")
// Setting the new Chat Id key created before
// on the "chatIds branch"
let chatIdKey = refChat.key
let refUserChatId = refUserChatIds.child(chatIdKey)
refUserChatIds.setValue(chatIdKey)
I think what you're looking for is this
let key = firebaseRef.child("users").child("\(String(describing: uid))").child("chatIds").childByAutoId().key
let timestamp = Int(Date().timeIntervalSince1970)
let child = ["key":key,
"name": name as String,
"date": birth as String,
"created": "\(timestamp)"]
firebaseRef.child("users").child("\(String(describing: uid!))").child("chatIds").child(key).setValue(child)
as example I'm saving the key, name, date, and created, as Childs of chatIds, with the childByAutoId, that generates you a random key, so you can locate it when searching the object.
import UIKit
import Firebase
class ChatListVC: UIViewController {
var ref: FIRDatabaseReference!
var messages: [FIRDataSnapshot]! = []
fileprivate var _refHandle: FIRDatabaseHandle?
override func viewDidLoad() {
super.viewDidLoad()
self.userDetail()
}
func userDetail(){
_refHandle = self.ref.child("users").child("child id").observe(.value, with: { [weak self] (snapshot) -> Void in
guard let strongSelf = self else { return }
guard let dict = snapshot.value as? [String:Any] else { return }
//access data from dict
let MyName = dict["MyName"] as? String ?? ""
})
}
Having a real hard time figuring this out. So if anyone could help would appreciate it. I have some data I want to pull from google firebase and store them into a struct them populate a tableview. But I have having some issues with the table being called before the data is all pulled. Im not sure if I'm using the right database calls for firebase but this is what I have so far.
struct provStru {
var name = String()
var last = String()
}
var store = [provStru]()
var ref: FIRDatabaseReference!
ref = FIRDatabase.database().reference()
var name = String()
var last = String()
var counter = 0
while counter<10 {
ref.child("Prov").child("\(counter + 1)").observeSingleEvent(of: .value, with: { (snapshot) in
// Get user value
if !snapshot.exists() {
print("doesnt exist")
} else {
let value = snapshot.value as? NSDictionary
name = value?["Name"] as! String
last = value?["Last"] as! String
self.store.append(provStru(name: name, last: last)
}
}) { (error) in
print(error.localizedDescription)
}
counter += 1
}
Then I would like to use that data from the struct to populate the tableview cells. But when I run this code the counter is like an infinite loop. Ive been trying to figure this out for a while. Thanks
This is how the data looks in firebase
This is what the database looks like then the next value would be 2 then 3 going down
Im new to using Firebase and am struggling to understand how to reach certain points of my firebase database using an ios query with swift.
My database looks something like this:
JSON DATABASE
Im trying to retrieve all the data and then target the location data to put pins on a mapview.
I have the Firebase and FirebaseDatabase pods built into my app with no problem but don't really know where to go from there.
Any help would be greatly appreciated
What I would do is the following:
First I would create a struct for People, to save a model for every Person entry.
You create a new Swift file and enter the following:
struct People {
var name: String = ""
var age: String = ""
var latitude: String = ""
var longitude: String = ""
var nationality: String = ""
}
Then, in your ViewController class, you create an NSArray of People and instantiate is as empty.
var peoples: [People] = []
Then you create a function to download your desired data.
func loadPeople() {
// first you need to get into your desired .child, what is in your case People
let usersRef = firebase.child("People")
usersRef.observeEventType(.Value, withBlock: { snapshot in
if snapshot.exists() {
// since we're using an observer, to handle the case
// that during runtime people might get appended to
// the firebase, we need to removeAll, so we don't
// store people multiple times
self.peoples.removeAll()
// then we sort our array by Name
let sorted = (snapshot.value!.allValues as NSArray).sortedArrayUsingDescriptors([NSSortDescriptor(key: "Name",ascending: false)])
for element in sorted {
let name = element.valueForKey("Name")! as? String
let age = element.valueForKey("age")! as? String
let location = element.valueForKey("location")! as? NSDictionary
let nationality = element.valueForKey("nationality")! as? String
// then we need to get our lat/long out of our location dict
let latitude = location.valueForKey("latitude")! as? String
let longitude = location.valueForKey("longitude")! as? String
// then we create a model of People
let p = People(name: name!, age: age!, latitude: latitude!, longitude: longitude!, nationality: nationality!)
// then we append it to our Array
self.tweets.append(t)
}
}
// if we want to populate a table view, we reload it here
// self.tableView.reloadData()
})
}
We need to call the function in viewDidAppear, after the UITableView for example, is loaded.
override viewDidAppear() {
loadPeople()
}
Now we have an Array of People and are able to populate a UITableView or print the values:
for p in peoples {
print("name = \(p.name)")
print("longitude = \(p.longitude)")
print("latitude = \(p.longitude)")
}