Hi I am doing a firebase call which is a query to check for the same posts related to a NSDictionary value. The snapshot prints the posts that I want but only 1 post is being displayed. I am trying to think of why it is only displaying 1 post but having a tough time with this.
func getAllPosts(refreshing: Bool, refreshControl: UIRefreshControl?) {
MBProgressHUD.showAdded(to: self.view, animated: true)
Database.database().reference().child("posts").child(self.otherUser?["uid"] as! String).queryOrdered(byChild: "uid").queryEqual(toValue: self.otherUser?["uid"] as! String).observe(.childAdded, with: { snapshot in
if snapshot.exists() {
print(snapshot)
if let dictionary = snapshot.value as? [String: AnyObject] {
self.feeds = []
let uid = dictionary["uid"] as? String
let name = dictionary["businessName"] as? String
let address = dictionary["businessStreet"] as? String
let state = dictionary["businessCity"] as? String
let caption = dictionary["caption"] as? String
let downloadURL = dictionary["download_url"] as? String
let timestamp = dictionary["timestamp"] as? Double
let date = Date(timeIntervalSince1970: timestamp!/1000)
let postID = dictionary["postID"] as? String
let lat = Double(dictionary["businessLatitude"] as! String)
let long = Double(dictionary["businessLongitude"] as! String)
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)
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
self.feeds.sort {$0.date.compare($1.date) == .orderedDescending}
self.feedTableView.reloadData()
}
if refreshing {
refreshControl?.endRefreshing()
}
MBProgressHUD.hide(for: self.view, animated: true)
} else {
print("No Snapshot found")
MBProgressHUD.hide(for: self.view, animated: true)
}
})
}
Related
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)
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)
}
}
Need help retrieving and setting an image from firebase. I am able to get the right URL for the image, but unsure on how to convert it to an actual picture I can share using the UIActivityViewController. "let titlePost = self.feeds[sender.tag].downloadURL" is what I am using to retrieve the specific image URL from a post from a tableview feed within my app. I have tried giving it a shot but need some help. Thank you
let shareAction = UIAlertAction(title: "Share", style: UIAlertActionStyle.default, handler: {(alert: UIAlertAction!) in
var objectsToShare: [AnyObject]?
let image: UIImage?
let titlePost = self.feeds[sender.tag].downloadURL
if let postURL = URL(string: titlePost) {
let postRequest = URLRequest(url: postURL)
image.setImageWith(postURL, placeholderImage: nil, options: SDWebImageOptions.progressiveDownload, completed: { (imageRequest, imageResponse, error) -> Void in
// failure downloading image
print("Error downloading Firebase post image")
print(error)
})
}
objectsToShare = [titlePost as AnyObject]
let activityViewController = UIActivityViewController(activityItems: objectsToShare!, applicationActivities: nil)
// present the view controller
self.present(activityViewController, animated: true, completion: nil)
})
Where I am pulling the image from
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if let cell = tableView.dequeueReusableCell(withIdentifier: "feedCell", for: indexPath) as? CustomerPostsViewCell {
let post = feeds[indexPath.row]
let caption = post.caption
let downloadURL = post.downloadURL
let name = post.name
let address = post.address
let state = post.state
let date = post.date
let distance = post.distance
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MM-dd-yyyy"
let dateString = dateFormatter.string(from: date)
// Business Name
cell.businessNameLabel.text = name
cell.businessAddressLabel.text = address
cell.businessStateLabel.text = state
cell.businessPostDistanceLabel.text = distance
// caption
cell.captionView.text = caption
// post image
cell.businessPostImage.image = nil
if let postURL = URL(string: downloadURL) {
let postRequest = URLRequest(url: postURL)
cell.businessPostImage.setImageWith(postURL, placeholderImage: nil, options: SDWebImageOptions.progressiveDownload, completed: { (imageRequest, imageResponse, error) -> Void in
// failure downloading image
print("Error downloading Firebase post image")
print(error)
})
}
// set date of post
cell.postTimeLabel.text = dateString
cell.optionsButton.tag = indexPath.row
cell.optionsButton.addTarget(self, action: #selector(optionsButton), for: .touchUpInside)
return cell
}
return UITableViewCell()
}
// MARK: Queries
func getAllPosts(refreshing: Bool, refreshControl: UIRefreshControl?) {
let ref = Database.database().reference().child("posts")
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 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)
self.feeds.append(post)
// sort posts by date/distance
//self.feeds.sort {$0.date.compare($1.date) == .orderedAscending}
self.feeds.sort {$0.distance.compare($1.distance) == .orderedAscending}
self.feedTableView.reloadData()
})
}
}
if refreshing {
refreshControl?.endRefreshing()
}
MBProgressHUD.hide(for: self.view, animated: true)
})
}
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
I have been knocking my head over this problem for a few days now. I have a function that
1) gets the snapshot values and then stores them into filteredLocations array
2) gets the location the user has pressed on the screen, then measures the distance between the two location points of where they pressed on the screen and the location from the snapshots
3) filters out the locations that meet the users radiusDistance and then places points on the map
The problem that I keep coming across though is with my print statements check 1 and check 2. They are being executed twice when it should only be once.
func addAnnotation(gestureRecognizer:UIGestureRecognizer){
filteredLocations.removeAll()
locations.removeAll()
let sampleRef = FIRDatabase.database().reference().child("SamplePost").child("post")
sampleRef.observeSingleEvent(of:.value, with: {(snapshot) in
if let result = snapshot.children.allObjects as? [FIRDataSnapshot] {
for child in result{
let dictionary = child.value as? [String: AnyObject]
let lat = dictionary?["lat"] as! Double
let long = dictionary?["long"] as! Double
let image = dictionary?["image"] as! String
let text = dictionary?["text"] as! String
let user = dictionary?["user"] as! String
let structure = MapPoints(Latitude: lat, Longitude: long, Image: image, Text: text, User: user)
self.filteredLocations.append(structure)
self.locations.append(structure)
print("check one \(self.filteredLocations.count)")
self.collectionView.reloadData()
}
}
let refined = Double(self.radiusDistanceNumber!)
print("check two \(self.filteredLocations.count)")
if gestureRecognizer.state == UIGestureRecognizerState.began{
self.removePointsAndClearArray()
let touchPoint = gestureRecognizer.location(in: self.mapView)
let newCoordinates = self.mapView.projection.coordinate(for: touchPoint)
let marker = GMSMarker(position: newCoordinates)
marker.title = "Selected location"
self.filteredLocations = self.locations.filter {
(locations) in
let userLocation = newCoordinates
let userLat = userLocation.latitude
let userLong = userLocation.longitude
let coordinateOne = CLLocation(latitude: userLat, longitude: userLong)
let coordinateTwo = CLLocation(latitude: CLLocationDegrees(locations.latitude!), longitude: CLLocationDegrees(locations.longitude!))
let distanceFromPoints = coordinateOne.distance(from: coordinateTwo)
let convertToMiles = distanceFromPoints*0.00062137
return convertToMiles < refined
}
print("check three \(self.filteredLocations.count)")
self.filteredLocations.map {
(location) in
let annotation = GMSMarker()
annotation.position = CLLocationCoordinate2D(latitude: CLLocationDegrees(location.latitude!), longitude: CLLocationDegrees(location.longitude!))
annotation.map = self.mapView
let camera = GMSCameraPosition.camera(withTarget: newCoordinates, zoom: 11)
self.mapView.animate(to: camera)
}
print("amount that is being counted \(self.filteredLocations.count)")
if self.filteredLocations.count <= 0 {
self.collectionView.isUserInteractionEnabled = false
} else{
self.collectionView.isUserInteractionEnabled = true
}
print("amount before reloading collectionView \(self.filteredLocations.count)")
self.collectionView.reloadData()
UIView.animate(withDuration: 0.3, delay: 0, options: .curveEaseIn, animations: {
})
}
})
}