public func getAllItems(completion: #escaping (Result<[Item], Error>) -> Void)
{
database.child("Items").observe(.value, with: {snapshot in
guard (snapshot.value as? [[String: Any]]) == nil else{
completion(.failure(DatabaseError.failedToFetch))
return
}
var newUrlArray: [Item] = []
var newItemArray: [Item] = []
for child in snapshot.children{
if let childSnapshots = child as? DataSnapshot,
let dict = childSnapshots.value as? [String:Any],
let title = dict["title"] as? String,
let content = dict["content"] as? String,
let itemId = dict["itemid"] as? String,
let price = dict["price"] as? Int{
let item = Item(title: title, content: content, itemId: itemId, price: price, urs: newUrlArray)
newItemArray.append(item)
}
}
completion(.success(newDataArray))
})
}
My question is how can I get urls that shown in picture as an array or is it possible.
You need to go one level deeper into your JSON/Snapshot hierarchy to get the URLs.
If I remove the non-URL code for a moment for readability, it'd be something like:
for child in snapshot.children{
if let childSnapshots = child as? DataSnapshot,
let dict = childSnapshots.value as? [String:Any],
let urls = childSnapshots.childSnapshot(atPath: "urls").value as? [String:Any],
...
}
}
So urls above is another dictionary, where you can loop over its keys to get the URL values.
Related
I'm trying to download user from Firebase and save them in an array using a Usermodel.
The download works so far, but how do I access the first user and show the picture of this user?
My Usermodel: Sorry for some German words
class UserModel {
var username: String?
var email: String?
var profilImageUrl: String
var birthdayDate: String?
var gender: String?
var userDescription: String?
init(dictionary: [String: Any]) {
username = dictionary["username"] as? String
email = dictionary["email"] as? String
profilImageUrl = dictionary["profilImageURL"] as? String ?? ""
birthdayDate = dictionary["Geburtsdatum"] as? String
gender = dictionary["gender"] as? String
userDescription = dictionary["description"] as? String
}
In the following I´m saving the downloaded Data to the array "attendees".The picture of the first user in this array should be shown in firstUserImageView.
import SDWebImage
var attendees = [UserModel]()
#IBOutlet weak var firstUserImageView: UIImageView!
//load attendees with Api -> that works.
print(attendees.count) gives me the amount of attendees saved in the database
func loadAttendees(){
guard let eventID = event?.id else {return}
AttendeeApi.shared.observeEventAttendee(eventID: eventID) { (attendeeId) in
AttendeeApi.shared.observeAttendee(attendeeId: attendeeId, completion: { (attendee) in
self.attendees.append(attendee)
})
}
}
Set up the image view
var attendee: UserModel?{
didSet {
let firstAttendee = attendees[0].profilImageUrl
guard let firstUserImageUrl = URL(string: firstAttendee) else {return}
firstUserImageView.sd_setImage(with: firstUserImageUrl) { (_, _, _, _) in
}
}
}
loadAttendees is called in viewDidLoad but the ImageView does not show the picture of the first user.
var REF_ATTENDEE = Database.database().reference().child("users")
func observeAttendee (attendeeId: String, completion: #escaping (UserModel) -> Void) {
REF_ATTENDEE.child(attendeeId).observeSingleEvent(of: .value) { (snapshot) in
guard let dic = snapshot.value as? [String: Any] else {return}
let newAttendee = UserModel(dictionary: dic)
completion(newAttendee)
}
}
var REF_EVENTS_ATTENDEES = Database.database().reference().child("events - attendees")
func observeEventAttendee(eventID: String, completion: #escaping (String) -> Void) {
REF_EVENTS_ATTENDEES.child(eventID).observe(.childAdded) { (snapshot) in
let attendeeId = snapshot.key
completion(attendeeId)
}
}
I've been trying to retrieve some data from firebase and store it in arrays. But I've got a problem when I try to append the data.
I can store the data into arrays only in the closure and outside of the closure, i all the sudden lose all the values inside of the arrays. Why does this happen? Please help me to find what I'm missing...
var names = [String]()
var txts = [String]()
var imgUrls = [String]()
Database.database().reference().child("Posts").child("dummy").observe(.value) { (snapshot) in
guard let snapshots = snapshot.children.allObjects as? [DataSnapshot] else {
return
}
for snap in snapshots {
let autoId = snap.key as String
Database.database().reference().child("Posts").child("dummy").child(autoId).observe(.value, with: { (snapshot) in
guard let data = snapshot.value as? [String: Any] else {return}
//name
guard let name = data["name"] as? String else {return}
self.names.append(name)
//image
guard let imgUrl = data["image"] as? String else {return}
self.imgUrls.append(imgUrl)
//txt
guard let txt = data["text"] as? String else {return}
self.txts.append(txt)
print(self.names) //this returns all data from firebase
print(self.imgUrls) //this returns all data from firebase
print(self.txts) //this returns all data from firebase
}
print(self.names) //this returns empty array
print(self.imgUrls) //this returns empty array
print(self.txts) //this returns empty array
}
Could it be because you are assigning the data inside a closure which could happen in a later time. So basically the last print statement occurs before the closure statements.
I will recommend you use didSet to understand the sequence. For example:
var names: [String] = [String]() {
didSet {
print(names) // this is print each time the value is set
}
}
var txts: [String] = [String]() {
didSet {
print(txts)
}
}
var imgUrls: [String] = [String]() {
didSet {
print(imgUrls)
}
}
Database.database().reference().child("Posts").child("dummy").observe(.value) { (snapshot) in
guard let snapshots = snapshot.children.allObjects as? [DataSnapshot] else { return }
for snap in snapshots {
let autoId = snap.key as String
Database.database().reference().child("Posts").child("dummy").child(autoId).observe(.value, with: { (snapshot) in
guard let data = snapshot.value as? [String: Any] else {return}
//name
guard let name = data["name"] as? String else {return}
self.names.append(name)
//image
guard let imgUrl = data["image"] as? String else {return}
self.imgUrls.append(imgUrl)
//txt
guard let txt = data["text"] as? String else {return}
self.txts.append(txt)
}
}
I want to retrieve all the values of 'itemname' from Firebase and put them in my array generatedObjects. Now it seems like i get the parent, and also the key and value of its children, when i only want all values of 'itemname' ('Toiletry bag', 'Toothbrush' etc.). Not sure where to go from here, appreciate any help:
My code:
self.ref.child("lists").child("-LOXr5PoUvBn_tGNhql-").child(whatList!).observeSingleEvent(of: .value, with: { (snapshot) in
let children = snapshot.children
while let rest = children.nextObject() as? DataSnapshot{
print(rest.value)
//self.generatedObjects.append(rest.value as! [String: AnyObject])
}
},withCancel: nil)
Try this
func getData() {
ref.child("lists").child("-LOXr5PoUvBn_tGNhql-").child("mylist").observe(.childAdded) { (snapshot) in
let result = snapshot.value as? [String: Any]
let item = result!["itemname"]
//append item to your array
...
}
}
func fetchdata(toId: String)
{
Database.database().reference().child("Users").child(toId).observeSingleEvent(of: .value) { (snapshot) in
guard let dictionary = snapshot.value as? [String:Any] else {return}
let itemname = dictionary["itemname"] as! String
print(itemname)
}
}
does it helpfull!!
In my viewController I have an array of class Users named arrayUtenti, with the code below I need to add that user to that array but for some reason that i cannot understand I get an empty array, what could happened?
**************EDITED WORKS**************
func vengodaEditPremuto(completionHandler:#escaping ([Users]) -> ()){ self.root.child("users").child("ZJq98gvOEHaLUqYTbp4xF52f2K23").observeSingleEvent(of: .value, with: { (snapshot) in
var TempArray: [Users] = []
guard
let value = snapshot.value as? [String:AnyObject],
let userid = value["id"],
let username = value["name"],
let useremail = value["email"]
else {return}
let utenteesistente = Users(id: userid as? String, name: username as? String, email: useremail as? String)
TempArray.append(utenteesistente)
self.arrayUtenti = TempArray
completionHandler(self.arrayUtenti)
print(self.arrayUtenti) //here is ok
})
print(self.arrayUtenti) //here the array is empty!!
}
Your code looks fine after my comment. This is the last thing you need to do to make a correct call:
vengodaEditPremuto(){ result in
print(result)
}
from this link I would like to get the commonName
I tried this but it didn't work?!
let commonName = object["toLocationDisambiguation"][0]["disambiguationOptions"][1]["place"][2]["commonName"].stringValue
Option 1 (Normal)
if let toLocationDisambiguation = object["toLocationDisambiguation"] as? Dictionary<String, AnyObject> {
if let disambiguationOptions = toLocationDisambiguation["disambiguationOptions"] as? Array<AnyObject> {
if let first = disambiguationOptions.first as? [String: AnyObject] {
if let place = first["place"] as? [String: AnyObject] {
let commonName = place["commonName"] as! String
print("Common Name: ", commonName)
}
}
}
}
Option 2 (Type Aliases)
typealias MyDictionary = [String: AnyObject]
typealias MyArray = [MyDictionary]
if let toLocationDisambiguation = object["toLocationDisambiguation"] as? MyDictionary {
if let disambiguationOptions = toLocationDisambiguation["disambiguationOptions"] as? MyArray {
if let first = disambiguationOptions.first {
if let place = first["place"] as? MyDictionary {
let commonName = place["commonName"] as! String
print("Common Name: ", commonName)
}
}
}
}
Option 3 (SwiftyJSON for Objective-C like syntax)
Take a look at SwiftyJSON.
let object = try! NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.AllowFragments) as! Dictionary<String, AnyObject>
let json = JSON(object)
let commonName = json["toLocationDisambiguation"]["disambiguationOptions"][0]["place"]["commonName"].stringValue
print("Common Name: ", commonName)