Using Firebase Location Coordinates - Cannot Load Annotations - ios

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)
}
}

Related

Zoom on multiple locations using 'MKMapView'

I am using the code below to retrieve data from MySQL to show multiple locations on MKMapView using Swift.
The data and locations shows on the map, but what I could not figure out is how to adjust the zoom to cover all locations in that area.
func parseJSON(_ data:Data) {
var jsonResult = NSArray()
do {
jsonResult = try JSONSerialization.jsonObject(with: data, options:JSONSerialization.ReadingOptions.allowFragments) as! NSArray
} catch let error as NSError {
print(error)
}
var jsonElement = NSDictionary()
let locations = NSMutableArray()
for i in 0 ..< jsonResult.count
{
jsonElement = jsonResult[i] as! NSDictionary
let location = LocationModel()
//the following insures none of the JsonElement values are nil through optional binding
if let evIdL = jsonElement["id"] as? String,
let evUserNameL = jsonElement["username"] as? String,
let evNotikindL = jsonElement["notikind"] as? String,
let evLatiL = jsonElement["lati"] as? String,
let evLongiL = jsonElement["longi"] as? String,
let evLocatL = jsonElement["locat"] as? String,
let evTimedateL = jsonElement["timedate"] as? String,
let evDistanceL = jsonElement["distance"] as? String
{
location.evId = evIdL
location.evUsername = evUserNameL
location.evNotikind = evNotikindL
location.evLati = evLatiL
location.evLongi = evLongiL
location.evLocat = evDistanceL
location.evTimedate = evTimedateL
location.evDisatnce = evDistanceL
location.evLocat = evLocatL
// the code to show locations
let latiCon = (location.evLati as NSString).doubleValue
let longiCon = (location.evLongi as NSString).doubleValue
let annotations = locations.map { location -> MKAnnotation in
let annotation = MKPointAnnotation()
annotation.title = evNotikindL
annotation.coordinate = CLLocationCoordinate2D(latitude:latiCon, longitude: longiCon)
return annotation
}
self.map.showAnnotations(annotations, animated: true)
self.map.addAnnotations(annotations)
}
locations.add(location)
}
DispatchQueue.main.async(execute: { () -> Void in
self.itemsDownloaded(items: locations)
})
}
I am using PHP file to connect with MySQL, as I said the code working and showing the locations but the zoom focus on one location only.
You can try
DispatchQueue.main.async {
self.map.addAnnotations(annotations)
self.map.showAnnotations(annotations, animated: true)
// make sure itemsDownloaded needs main ??
self.itemsDownloaded(items: locations)
}

Swift firebase get data

How can I get name, quant from this structure:
Im try this:
var handle: DatabaseHandle?
var ref: DatabaseReference?
override func viewDidLoad() {
super.viewDidLoad()
ref = Database.database().reference()
handle = ref?.child("Цитаты").child("Из Книг").child("Дорогой звезд").child("Quote1").observe(.childAdded, with: { (snapshot) in
let user = snapshot.value
print(user!) //text from name + 10 + Quote1
}
When I print snapshot.value it's give me data from Quote1 , but I want to show name in textField and quant in label I try this:
ref = Database.database().reference()
handle = ref?.child("Цитаты").child("Из Книг").child("Дорогой звезд").child("Quote1").observe(.childAdded, with: { (snapshot) in
let user = snapshot.value
if let us = user!["name"] as? String {
if let quant = user!["quant"] as? String{
self.quoteTextField.text = us
self.quotelabel.text = quant
}
}
And have error. How can I add data from snapshot.value to label and textField?
As I was checking your screen, quant is an Int not String, so try this
ref = Database.database().reference()
handle = ref?.child("Цитаты").child("Из Книг").child("Дорогой звезд").child("Quote1").observe(.childAdded, with: { (snapshot) in
//let username = snapshot.value as? NSDictionary
let user = snapshot.value as? [String: Any]
if let us = user!["name"] as? String {
if let quant = user!["quant"] as? Int {
self.quoteTextField.text = us
self.quotelabel.text = quant.description
}
}
}
You need to cast the snapshot.value as a dictionary -
let user = snapshot.value as? NSDictionary
You should also consider safely unwrapping your optionals -
let name = user?["name"] as? String ?? ""
let quant = user?["quant"] as? Int ?? 0

Swift Firebase QueryLimitedToFirst

Hi I am trying to limit a feed to the most recent two posts from users. I was reading the Firebase documentation and it said simply to add "queryLimited(toFirst: Int)" and so far it has not been working, my feed still retrieves all the posts from each user. At the very top is where I have implemented the "queryLimited".
Edit
The way my code is right now, it is only limiting the users and not the posts(json tree below) so how can I change it to limit the posts of each user?
func getAllPosts(refreshing: Bool, refreshControl: UIRefreshControl?) {
let ref = Database.database().reference().child("posts").queryLimited(toFirst: 2)
MBProgressHUD.showAdded(to: self.view, animated: true)
ref.queryOrdered(byChild: "businessName").observe(.childAdded, with: { snapshot in
//observeSingleEvent(of: .value, with: { snapshot in
if let dict = snapshot.value as? NSDictionary {
self.feeds = []
for item in dict {
let json = JSON(item.value)
let uid = json["uid"].stringValue
var name: String = json["businessName"].stringValue
let address: String = json["businessStreet"].stringValue
let state: String = json["businessCity"].stringValue
let caption: String = json["caption"].stringValue
let downloadURL: String = json["download_url"].stringValue
let timestamp = json["timestamp"].doubleValue
let date = Date(timeIntervalSince1970: timestamp/1000)
let postID: String = json["postID"].stringValue
let lat = json["businessLatitude"].doubleValue
let long = json["businessLongitude"].doubleValue
let businessLocation = CLLocation(latitude: lat, longitude: long)
let latitude = self.locationManager.location?.coordinate.latitude
let longitude = self.locationManager.location?.coordinate.longitude
let userLocation = CLLocation(latitude: latitude!, longitude: longitude!)
let distanceInMeters: Double = userLocation.distance(from: businessLocation)
let distanceInMiles: Double = distanceInMeters * 0.00062137
let distanceLabelText = String(format: "%.2f miles away", distanceInMiles)
self.uid = json["uid"].stringValue
let usersReference = Database.database().reference(withPath: "users").queryOrderedByKey().queryEqual(toValue: uid)
usersReference.observeSingleEvent(of: .value, with: { snapshot in
if let dict = snapshot.value as? NSDictionary {
let userInfo = dict.allValues[0]
let userJSON = JSON(userInfo)
name = userJSON["name"].stringValue
}
let post = Post(uid: uid, caption: caption, downloadURL: downloadURL, name: name, date: date, address: address, state: state, distance: distanceLabelText, postID: postID)
self.feeds.append(post)
// sort posts by date/distance
self.feeds.sort {$0.date.compare($1.date) == .orderedDescending}
self.feeds.sort {$0.distance.compare($1.distance) == .orderedAscending}
self.feedTableView.reloadData()
})
}
}
if refreshing {
refreshControl?.endRefreshing()
}
MBProgressHUD.hide(for: self.view, animated: true)
})
}
I'm pretty sure that the order query must precede the limit query.
let ref = Database.database().reference().child("posts").queryOrdered(byChild: "businessName").queryLimited(toFirst: 2)

How to include firebase snapshot key value? [Swift]

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

Add annotation after retrieving users latitude and longitude from Firebase

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.

Resources