I am trying to add a mapView annotation of all the online user after retrieving their latitude and longitude from Firebase. I am able to print it as an optional or as a CLLocationDegrees aka Double, but when I try to add it into my user.userAnnotation attribute I get a fatal error. This is what I am printing:
this is the users lat Optional(19.435477800000001)
this is the user latitude in CLLocationDegrees 19.4354778
fatal error: unexpectedly found nil while unwrapping an Optional value
And this is my function:
func fetchOnlineUsers() {
ref = FIRDatabase.database().reference()
FIRDatabase.database().reference().child("users").observe(.childAdded, with: { (snapshot) in
if let dictionary = snapshot.value as? [String: AnyObject] {
let user = AppUser()
user.userEmail = (snapshot.value as? NSDictionary)?["name"] as? String
user.latitude = (snapshot.value as? NSDictionary)?["latitude"] as? Double
user.longitude = (snapshot.value as? NSDictionary)?["longitude"] as? Double
user.online = ((snapshot.value as? NSDictionary)?["online"] as? Bool)!
print("this is the user latitude \(user.latitude)")
let userLat = CLLocationDegrees(user.latitude!)
let userLon = CLLocationDegrees(user.longitude!)
if user.online == true {
user.userAnnotation.coordinate = CLLocationCoordinate2D(latitude: userLat, longitude: userLon)
self.users.append(user)
}
print("this are the users \(self.users)")
print("this is the dictionary \(dictionary)")
self.mainMapView.addAnnotations([user.userAnnotation])
}
}, withCancel: nil)
}
Well some of the value/s that you´re getting is nil. Try this instead:
guard let dictionary = snapshot.value as? [String: AnyObject],
let email = (snapshot.value as? NSDictionary)?["name"] as? String,
let latitude = (snapshot.value as? NSDictionary)?["latitude"] as? Double,
let longitude = (snapshot.value as? NSDictionary)?["longitude"] as? Double,
let online = ((snapshot.value as? NSDictionary)?["online"] as? Bool)! else { // Some error }
If this succeeds you can start use the variables created in the guard let and they will 1: have a value, 2: not be Optional.
Related
I am manually entering in data into my database and the only variable not getting passed from my database is the author and I do not know where I am going wrong.
func getAllArticles(handler: #escaping (_ articles: [Article])-> ()){
var articleArray = [Article]()
REF_ARTICLES.observeSingleEvent(of: .value) { (articleMessageSnapshot) in
guard let articleMessageSnapshot = articleMessageSnapshot.children.allObjects as? [DataSnapshot] else {return}
for article in articleMessageSnapshot {
let content = article.childSnapshot(forPath: "content").value as? String ?? "no content"
let author = article.childSnapshot(forPath: "author").value as? String ?? "no author"
let twitterHandle = article.childSnapshot(forPath: "twitterHandle").value as? String ?? "none"
let articleTitle = article.childSnapshot(forPath: "articleTitle").value as? String ?? "no title"
let date = article.childSnapshot(forPath: "date").value as? String ?? "no date"
let article = Article(content: content, author: author, twitterHandle: twitterHandle, ArticleTitle: articleTitle, date: date)
articleArray.append(article)
}
handler(articleArray)
}
}
Please check out below code
var articleArray = [Article]()
//REF_ARTICLES
let ref = Database.database().reference().child(“articles”)
ref.observe(.childAdded, with: { (snapshot) in
print(snapshot)
guard let dictionary = snapshot.value as? [String : AnyObject] else {
return
}
let articleObj = Article()
articleObj.Content = dictionary["content"] as? String
articleObj.Author = dictionary["author"] as? String
articleObj.Twitterhandle = dictionary["twitterHandle"] as? String
articleObj.Title = dictionary["articleTitle"] as? String
articleObj.Date = dictionary["date"] as? String
self. articleArray.append(articleObj)
}, withCancel: nil)
}
I am also working on similar app where i am storing data to firebase and retrieving. Below approach i used to fetch the data from firebase database. Please try once.
func getAllArticles(handler: #escaping (_ articles: [Article])-> ()) {
Database.database().reference().child("Articles").observe(.childAdded, with: { (snapshot) in
print("articles = \(snapshot)")
if let dict = snapshot.value as? [String: Any] {
let article = Article()
article.articleTitle = dict["articleTitle"] as? String
article.author = dict["author"] as? String
article.twitterHandle = dict["twitterHandle"] as? String
article.date = dict["date"] as? String
article.content = dict["content"] as? String
self.articleArray.append(article)
}
handler(articleArray)
}, withCancel: nil)
}
im not sure what the underlying issue was, but i fixed it by deleting "author" from the firebase tree and then adding it back
I am currently trying to plug in a users coordinates from firebase into my function that will then represent these coordinates on my map. I don't know if this has something to do with me changing the coordinates from a string to a double.
An issue could also be that swift is not recognizing mapView as a part of the viewcontroller's class. I used my #IBOutlet weak var map: MKMapView! as a replacement in hopes that the annotations would show.
func retrieveUsers(){
let ref = Database.database().reference()
ref.child("users").queryOrderedByKey().observeSingleEvent(of: .value, with: { snapshot in
let users = snapshot.value as! [String: AnyObject]
self.user.removeAll()
for (_,value) in users {
if let uid = value["uid"] as? String {
if uid != Auth.auth().currentUser!.uid {
let userToShow = User()
if let fullName = value["full name"] as? String, let imagePath = value["urlToImage"] as? String
,let snap = snapshot.value as? [String: Any],
let userLongitude = Double(snap["long"] as! String),
let userLatitude = Double(snap["lat"] as! String)
{
let otherUserLocation:CLLocationCoordinate2D = CLLocationCoordinate2D(latitude: userLatitude, longitude: userLongitude)
let userAnnotation = MKPointAnnotation()
userAnnotation.coordinate = otherUserLocation
userAnnotation.title = fullName
DispatchQueue.main.async {
self.map.addAnnotation(userAnnotation)
}
}
Please anyone who would show me how to include the snapshot key value along with children value that I already append to my array (forgot to include it and now remember I have to) ... aside from that something really I couldn't understand when I tried to solve my own issue, by testing the value first by using this method: print(rooms.popFirst().key!) half of my database values got nil value ?!! and if I don't include that method everything works fine anyways if you can't imagine that nonetheless I really wish your suggestion or advice for getting all data with their own key value...
This is my code so far:
Database.database().reference().child("rooms").observe(.value, with: { (snapshot) in
print()
var rooms = snapshot.value as! [String:AnyObject]
for(_,value) in rooms {
if (rooms.popFirst()?.key) != nil{
let title = value["title"] as? String
let description = value["description"] as? String
let roomPictureUrl = value["Room Picture"] as? String
let longitude = value["Longtitude"] as? String
let latitude = value["Latitude"] as? String
let dateFrom = value["Date From"] as? String
let dateTo = value["Date To"] as? String
let owner = value["Owner"] as? String
let myRooms = Room(roomID: "XXX",title: title!, description: description!, roomPicutreURL: roomPictureUrl!, longitude: longitude!, latitude: latitude!, dateFrom: dateFrom!, dateTo: dateTo!, owner: owner!)
//print(rooms.popFirst()?.key)
self.rooms.append(myRooms)
self.tableView.reloadData()
}
}
})
Try this:
Database.database().reference().child("rooms").observe(.value, with: { (snapshot) in
var rooms = snapshot.value as! [String:AnyObject]
let roomKeys = Array(rooms.keys)
for roomKey in roomKeys {
guard
let value = rooms[roomKey] as? [String:AnyObject]
else
{
continue
}
let title = value["title"] as? String
let description = value["description"] as? String
let roomPictureUrl = value["Room Picture"] as? String
let longitude = value["Longtitude"] as? String
let latitude = value["Latitude"] as? String
let dateFrom = value["Date From"] as? String
let dateTo = value["Date To"] as? String
let owner = value["Owner"] as? String
let myRooms = Room(roomID: "XXX",title: title!, description: description!, roomPicutreURL: roomPictureUrl!, longitude: longitude!, latitude: latitude!, dateFrom: dateFrom!, dateTo: dateTo!, owner: owner!)
print(roomKey)
self.rooms.append(myRooms)
self.tableView.reloadData()
}
}
})
To get the key from snapshot you can use following lines of code it will give you result like -> Kqwewsds12 -> your child Details
let dictValues = [String](snapshot.keys)
print(dictValues[0]) //Output -- Kqwewsds12
Hey I am new with Firebase and I got problem with getting data from database, I get error on this line:
let snapshotValue = snapshot.value as! [String: AnyObject]
Could you help me with fixing this problem?
Error says:
Could not cast value of type '__NSCFString' (0x1a8e00d50) to 'NSDictionary' (0x1a8e01c78).
event controller:
init(snapshot: FIRDataSnapshot) {
key = snapshot.key
let snapshotValue = snapshot.value as! [String: AnyObject]
name = snapshotValue["name"] as! String
addedByUser = snapshotValue["addedByUser"] as! String
startTime = snapshotValue["startTime"] as! Double
endPickerTime = snapshotValue["endPickerTime"] as! Double
longtitude = snapshotValue["longtitude"] as! Double
latitude = snapshotValue["latitude"] as! Double
eventImageStringUrl = snapshotValue["eventImageStringUrl"] as! String
eventId = snapshotValue["eventId"] as! String
eventDescription = snapshotValue["eventDescription"] as! String
completed = snapshotValue["completed"] as! Bool
ref = snapshot.ref
}
Getting data from database:
override func viewDidLoad() {
super.viewDidLoad()
databaseHandle = databaseRef.child("events").observe(.childAdded, with: { (snapshot) in
var newItems: [Event] = []
for item in snapshot.children {
let event = Event(snapshot: item as! FIRDataSnapshot)
newItems.append(event)
}
})
Database scheme:
Change .childAdded to .value in .observe.
I'm not sure how to fix this error. Can someone explain it?
Type 'NSFastEnumerationIterator.Element' (aka 'Any') does not conform to protocol 'AnyObject'
Here's my Query.
media24HourQuery.observe(FIRDataEventType.value, with: { snapshot in
var newItems = [[String: AnyObject]]()
for child in snapshot.children {
let title = (child as AnyObject).value["title"] as? String
let userID = (child as AnyObject).value["userID"] as? String
let mediaID = (child as AnyObject).value["mediaID"] as? String
let timestamp = (child as AnyObject).value["timestamp"] as? Double
edit: this doesn't work either (everything is nil)
for _ in snapshot.children {
let title = (snapshot.value as? NSDictionary)?["title"] as? String
let userID = (snapshot.value as? NSDictionary)?["userID"] as? String
let mediaID = (snapshot.value as? NSDictionary)?["mediaID"] as? String
let timestamp = (snapshot.value as? NSDictionary)?["timestamp"] as? Double
and if I do print (child), this is what I get:
// print(child)
Snap (XsUwNDQB3qPdjYFCOLzANmsjjpf1-1474144681) {
mediaID = "XsUwNDQB3qPdjYFCOLzANmsjjpf1-1474144681";
timestamp = 1474144681490;
title = "outside sep 17";
userID = XsUwNDQB3qPdjYFCOLzANmsjjpf1;
}
edit: solved it. this works:
let snapDic = snapshot.value as? NSDictionary
for child in snapDic! {
print (child)
let childDic = child.value as? NSDictionary
let title = childDic?["title"] as? String
let userID = childDic?["userID"] as? String
let mediaID = childDic?["mediaID"] as? String
let timestamp = childDic?["timestamp"] as? Double