I have a question regarding creating a Apple Map Overlay. I am trying to set on odd shape overlay from a JSON file. I have researched this on Stack Overflow, and have tried many of the solutions, but none seem to work. My code is below:
import UIKit
import MapKit
import CoreLocation
class ViewController: UIViewController, CLLocationManagerDelegate, MKMapViewDelegate, UIGestureRecognizerDelegate {
#IBOutlet weak var mapView: MKMapView!
var coordinate: CLLocationCoordinate2D?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
mapView.showsUserLocation = true
mapView.delegate = self
mapView.mapType = .standard
let gestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.TapGesture))
mapView.addGestureRecognizer(gestureRecognizer)
}
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
if overlay is MKPolygon {
let polygonView = MKPolygonRenderer(overlay: overlay)
polygonView.strokeColor = UIColor.black
polygonView.lineWidth = 0.5
polygonView.fillColor = UIColor.blue
return polygonView
}
return MKOverlayRenderer()
}
#objc func TapGesture(gesRect: UITapGestureRecognizer) {
let location = gesRect.location(in: mapView)
coordinate = mapView.convert(location,toCoordinateFrom: mapView)
let locCoord = mapView.convert(location, toCoordinateFrom: mapView)
print("Tapped at lat: \(locCoord.latitude) long: \(locCoord.longitude)")
print("Tapped at: \(location)")
self.retreiveShape() { (full_shape) in
if let shape = full_shape {
let polygon = MKPolygon.init(coordinates: shape, count: shape.count)
self.mapView.addOverlay(polygon)
} else {
print("ARRAY EMPTY")
}
}
}
func retreiveShape(completion: #escaping ([CLLocationCoordinate2D]?) -> ()) {
let path = Bundle.main.path(forResource: "shape", ofType: "json")
var coord_array = [CLLocationCoordinate2D]()
do {
let data = try Data.init(contentsOf: URL.init(fileURLWithPath: path!))
let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments)
if let dictionary = json as? [String: Any] {
if let shape = dictionary["shape"] as? Array<Any> {
for regions in shape {
guard let region = regions as? Array<Array<Array<Double>>> else {
print("NOT HAPPENING")
return
}
for sections in region {
for coord in sections {
print("LATITUDE: \(coord[0])", "LONGITUDE: \(coord[1])")
let coordinatesToAppend = CLLocationCoordinate2D(latitude: coord[0], longitude: coord[1])
coord_array.append(coordinatesToAppend)
}
}
}
completion(coord_array)
}
}
} catch let error {
print(error)
}
}
The shape.json file is below:
{
"shape":[
[
[
[-81.621199, 30.282314],
[-81.613987, 30.281941],
[-81.611277, 30.284743],
[-81.602735, 30.284026],
[-81.601978, 30.292561],
[-81.596275, 30.290861],
[-81.592406, 30.290182],
[-81.571146, 30.28763],
[-81.55922, 30.286602],
[-81.559148, 30.291132],
[-81.558633, 30.294747],
[-81.55881, 30.312887],
[-81.558601, 30.312888],
[-81.558622, 30.316235],
[-81.558313, 30.316828],
[-81.552252, 30.320252],
[-81.548471, 30.321618],
[-81.527882, 30.323989],
[-81.529486, 30.328076],
[-81.537635, 30.336704],
[-81.537706, 30.337221],
[-81.538717, 30.338277],
[-81.539343, 30.338462],
[-81.542809, 30.341686],
[-81.547286, 30.345211],
[-81.552498, 30.348839],
[-81.552559, 30.352445],
[-81.577566, 30.352039],
[-81.578098, 30.353324],
[-81.578161, 30.35642],
[-81.577294, 30.3596],
[-81.576996, 30.366609],
[-81.58011, 30.366553],
[-81.580875, 30.37062],
[-81.580844, 30.373862],
[-81.581462, 30.374486],
[-81.578114, 30.374236],
[-81.572908, 30.374611],
[-81.562232, 30.372303],
[-81.551965, 30.366559],
[-81.548676, 30.365568],
[-81.540187, 30.378172],
[-81.538175, 30.380467],
[-81.538213, 30.387239],
[-81.536613, 30.388739],
[-81.512612, 30.392739],
[-81.505211, 30.390739],
[-81.490911, 30.392139],
[-81.49085, 30.389014],
[-81.489978, 30.389207],
[-81.488818, 30.38775],
[-81.489203, 30.389266],
[-81.487056, 30.390019],
[-81.481446, 30.391262],
[-81.479505, 30.39117],
[-81.477708, 30.390635],
[-81.476792, 30.390609],
[-81.476244, 30.391002],
[-81.473212, 30.389422],
[-81.472125, 30.388436],
[-81.472225, 30.388071],
[-81.474072, 30.386758],
[-81.475085, 30.384287],
[-81.474394, 30.381898],
[-81.473246, 30.38059],
[-81.473337, 30.380112],
[-81.47295, 30.379864],
[-81.472643, 30.380053],
[-81.471914, 30.379532],
[-81.471629, 30.378346],
[-81.470845, 30.377256],
[-81.468671, 30.376016],
[-81.466871, 30.374481],
[-81.465402, 30.374424],
[-81.464374, 30.373764],
[-81.465116, 30.373015],
[-81.467728, 30.372493],
[-81.469102, 30.371435],
[-81.470279, 30.369931],
[-81.472008, 30.370608],
[-81.473695, 30.370041],
[-81.471862, 30.370238],
[-81.470952, 30.369737],
[-81.471715, 30.369462],
[-81.470506, 30.369378],
[-81.469456, 30.368207],
[-81.468051, 30.367707],
[-81.46754, 30.366828],
[-81.466905, 30.366464],
[-81.467432, 30.366219],
[-81.466928, 30.365735],
[-81.465222, 30.365136],
[-81.464909, 30.364103],
[-81.46316, 30.362764],
[-81.463369, 30.36188],
[-81.462197, 30.361235],
[-81.461151, 30.36123],
[-81.46117, 30.360531],
[-81.461878, 30.360305],
[-81.461619, 30.359642],
[-81.461873, 30.358669],
[-81.461645, 30.358376],
[-81.460504, 30.358329],
[-81.46288, 30.357969],
[-81.462786, 30.357137],
[-81.461247, 30.355282],
[-81.460556, 30.352518],
[-81.46184, 30.340222],
[-81.462497, 30.339325],
[-81.465064, 30.337897],
[-81.471588, 30.328301],
[-81.472988, 30.318258],
[-81.469123, 30.319481],
[-81.450496, 30.320896],
[-81.443818, 30.302908],
[-81.442451, 30.301512],
[-81.438991, 30.299798],
[-81.437921, 30.298031],
[-81.437696, 30.284657],
[-81.438134, 30.283427],
[-81.439935, 30.281191],
[-81.440578, 30.279729],
[-81.440309, 30.276152],
[-81.441217, 30.271746],
[-81.440891, 30.270368],
[-81.440247, 30.269313],
[-81.438555, 30.267721],
[-81.43765, 30.266188],
[-81.43705, 30.257116],
[-81.441869, 30.256519],
[-81.45385, 30.252008],
[-81.466184, 30.251073],
[-81.472173, 30.251296],
[-81.491372, 30.251034],
[-81.507105, 30.253603],
[-81.510744, 30.253761],
[-81.530261, 30.250144],
[-81.56957, 30.249854],
[-81.584658, 30.251369],
[-81.586895, 30.251326],
[-81.589607, 30.250593],
[-81.593308, 30.248471],
[-81.605497, 30.260294],
[-81.621493, 30.282334],
[-81.621199, 30.282314]
]
]
]
}
It should create an odd shape overlay in the Southside of Jacksonville,FL, but it isn't. When the completion block is called the Coordinates are added to the array, but the map overlay isn't showing. Any thoughts?
Well this is somewhat embarrassing. I did as was suggested in the comments, and tried having the shape with nine vertices. It still didn't work. I then changed the coord from:
print("LATITUDE: \(coord[0])", "LONGITUDE: \(coord[1])")
let coordinatesToAppend = CLLocationCoordinate2D(latitude: coord[0], longitude: coord[1])
to:
print("LATITUDE: \(coord[1])", "LONGITUDE: \(coord[0])")
let coordinatesToAppend = CLLocationCoordinate2D(latitude: coord[1], longitude: coord[0])
It works perfectly. Turns out I had the Latitude and Longitude wrong.
I am using firebase swift 3. I am new in firebase. So I build an application which user can sign up and post an event, other user can view events and click on attend button if they want to attend. Successfully I can implement all this but my problem is when user click on attend button it will save as user uid under peoplewhoattend child. now I want to view those people who will attend the event. I think I should link user uid to user profile but I can not do that. I have tried a lot and find some similar question but nothing work with me. Here is my code. Rhanks in advance for every positive comment and help
this is attend action button
#IBAction func btnAttend(_ sender: Any) {
self.btnattend.isEnabled = true
let dbRef = Database.database().reference()
let uid = Auth.auth().currentUser!.uid
let storageRef = Storage.storage().reference(forURL: "gs://event-f39cc.appspot.com")
let key = dbRef.child("posts").childByAutoId().key
let imageRef = storageRef.child("posts").child(uid).child("\(key).jpg")
let data = UIImageJPEGRepresentation(self.imgEvent.image!, 0.5)
dbRef.child("users").child("posts").child(self.EventId!).observeSingleEvent(of: .value, with: { (snapshot) in
let updateattends = ["peopleWhoattend/\(key)" : Auth.auth().currentUser!.uid , "UserEmail" : Auth.auth().currentUser?.email , "Username" : Auth.auth().currentUser?.displayName] as [String: Any]
dbRef.child("posts").child(self.EventId!).updateChildValues(updateattends, withCompletionBlock: {(error, reff) in
if error == nil{
dbRef.child("posts").child(self.EventId!).observeSingleEvent(of: .value, with: {(snap) in
if let properties = snap.value as? [String: AnyObject] {
if let Attend = properties["peopleWhoattend"] as? [String: AnyObject]{
let count = Attend.count
self.lblattend.text = "\(count)"
let update = ["Attend" : count]
dbRef.child("posts").child(self.EventId!).updateChildValues(update)
self.btnattend.isHidden = false
// self.unlikeBtn.isHidden = false
//self.unlikeBtn.isEnabled = true
}
}
})
}
})
})
dbRef.removeAllObservers()
}
my database on firebase in JASON format
<pre>
{
"posts" : {
"-KrbDH19ERe9Os5RrEin" : {
"Attend" : 10,
"Category" : "Film & Media",
"Event date End" : "15/08/2017 10:47 PM",
"Event date Start" : "15/08/2017 10:47 PM",
"EventId" : "-KrbDH19ERe9Os5RrEin",
"EventTitle" : "hhh",
"Fee" : "6",
"Location" : {
"latitude" : 23.61349209999999,
"longitude" : 58.5434909,
"place name" : "Ruwi St, Muscat, Oman"
},
"User Email" : "salwa#hotmail.com",
"author" : "abeer",
"commentsId" : "-KrbDH19ERe9Os5RrEio",
"description" : "Event Description : dsdss",
"likes" : 3,
"pathToImage" : "https://firebasestorage.googleapis.com/v0/b/event-f39cc.appspot.com/o/events%2FhjAPqucu2jh3sY6v9n9nRM5Fuz73%2F-KrbDH19ERe9Os5RrEin.jpg?alt=media&token=795f2555-f36d-49d7-9bdd-e521fcd14c16",
"peopleWhoLike" : {
"-KrdnWbWtQ7zmkVwN7MZ" : "hjAPqucu2jh3sY6v9n9nRM5Fuz73",
"-Krdnymu9a_zP81JFDzm" : "hjAPqucu2jh3sY6v9n9nRM5Fuz73",
"-KsZb-WL9dptWI7dHWDf" : "3IHHOBRaVyR3ldK4hGtcGoY7lox2"
},
"peopleWhoattend" : {
"-KrbDLO6ZIpIxt4lTax0" : "hjAPqucu2jh3sY6v9n9nRM5Fuz73",
"-KrbDMri-KrHDrvCAHS4" : "hjAPqucu2jh3sY6v9n9nRM5Fuz73",
"-KrbE3OppAyB_zI5XacN" : "hjAPqucu2jh3sY6v9n9nRM5Fuz73",
"-KrbE3bgAZgvLs9J2KJr" : "hjAPqucu2jh3sY6v9n9nRM5Fuz73",
"-KrbE3vSo1Z6EqOAO4SJ" : "hjAPqucu2jh3sY6v9n9nRM5Fuz73",
"-KrbE4H_kpwgsMRlRCt6" : "hjAPqucu2jh3sY6v9n9nRM5Fuz73",
"-KrbE4Xa2CP_KXC8dQbi" : "hjAPqucu2jh3sY6v9n9nRM5Fuz73",
"-KtL2Egv2slRRk8f_rF1" : "H5kCOhIQFMbxQlN5dzZYC8aptxR2",
"-KtL2TXGz5JkCd1vA3Z2" : "H5kCOhIQFMbxQlN5dzZYC8aptxR2",
"-KtL2TtWdIFn3I1zvMAD" : "H5kCOhIQFMbxQlN5dzZYC8aptxR2"
},
"userId" : "hjAPqucu2jh3sY6v9n9nRM5Fuz73",
"username" : "Salwa"
},
"-KrdlVlme6Jc6eVbNBTa" : {
"Attend" : 4,
"Category" : "Science & Technology",
"Event date End" : "20/08/2017 10:40 AM",
"Event date Start" : "16/08/2017 10:40 AM",
"EventId" : "-KrdlVlme6Jc6eVbNBTa",
"EventTitle" : "hhhh",
"Fee" : "6666",
"Location" : {
"latitude" : 23.6006718,
"longitude" : 58.55438340000001,
"place name" : "(Great Valley (Alkbir Wadi, Muscat, Oman"
},
"User Email" : "salwa#hotmail.com",
"author" : "abeer",
"commentsId" : "-KrdlVlme6Jc6eVbNBTb",
"description" : "Event Description : ttttt",
"likes" : 5,
"pathToImage" : "https://firebasestorage.googleapis.com/v0/b/event-f39cc.appspot.com/o/events%2FhjAPqucu2jh3sY6v9n9nRM5Fuz73%2F-KrdlVlme6Jc6eVbNBTa.jpg?alt=media&token=4471c063-5432-474e-82b3-030f44ce231f",
"peopleWhoLike" : {
"-Krdlhj9fflCIEguJlPZ" : "hjAPqucu2jh3sY6v9n9nRM5Fuz73",
"-KrdlhtXEdxuUMRfYJsR" : "hjAPqucu2jh3sY6v9n9nRM5Fuz73",
"-Krdlhz1914-GsfDsK21" : "hjAPqucu2jh3sY6v9n9nRM5Fuz73",
"-KsZDW38ka7dB5NtfrNm" : "Rufida",
"-KsnWCXJNFlZJT5qbh8J" : "FWTfyvXqsXXdI9sy3GihCx8o5a63"
},
"peopleWhoattend" : {
"-Krdlbv9aKWlYNGa1K_d" : "hjAPqucu2jh3sY6v9n9nRM5Fuz73",
"-Krdldu17azum7ZH5u-E" : "hjAPqucu2jh3sY6v9n9nRM5Fuz73",
"-KrdlgBey4dkBLY8FBBK" : "hjAPqucu2jh3sY6v9n9nRM5Fuz73",
"-KtL2V0WEYwRLCLpGvvW" : "H5kCOhIQFMbxQlN5dzZYC8aptxR2"
},
"user name" : "rufida#hotmail.com",
"userId" : "hjAPqucu2jh3sY6v9n9nRM5Fuz73",
"username" : "Salwa"
},
"users" : {
"3IHHOBRaVyR3ldK4hGtcGoY7lox2" : {
"name" : "Rufida",
"uid" : "3IHHOBRaVyR3ldK4hGtcGoY7lox2",
"urlToImage" : "https://firebasestorage.googleapis.com/v0/b/event-f39cc.appspot.com/o/users%2F3IHHOBRaVyR3ldK4hGtcGoY7lox2.jpg?alt=media&token=1c3ee6f2-f688-40b4-b1d6-69f90bf19bb1"
},
"FWTfyvXqsXXdI9sy3GihCx8o5a63" : {
"Email" : "Ola#hotmail.com",
"name" : "Ola",
"uid" : "FWTfyvXqsXXdI9sy3GihCx8o5a63",
"urlToImage" : "https://firebasestorage.googleapis.com/v0/b/event-f39cc.appspot.com/o/users%2FFWTfyvXqsXXdI9sy3GihCx8o5a63.jpg?alt=media&token=289d9b9c-65c1-4ac0-83e4-7f688925f927"
},
"H5kCOhIQFMbxQlN5dzZYC8aptxR2" : {
"Email" : "Salwa#hotmail.com",
"name" : "Salwa",
"uid" : "H5kCOhIQFMbxQlN5dzZYC8aptxR2",
"urlToImage" : "https://firebasestorage.googleapis.com/v0/b/event-f39cc.appspot.com/o/users%2FH5kCOhIQFMbxQlN5dzZYC8aptxR2.jpg?alt=media&token=8f676259-7240-43d2-8735-0896ec9ad090"
},
"hjAPqucu2jh3sY6v9n9nRM5Fuz73" : {
"name" : "abeer",
"uid" : "hjAPqucu2jh3sY6v9n9nRM5Fuz73",
"urlToImage" : "https://firebasestorage.googleapis.com/v0/b/event-f39cc.appspot.com/o/users%2FhjAPqucu2jh3sY6v9n9nRM5Fuz73.jpg?alt=media&token=2c343a4c-c6ad-4dcf-bd0d-10e9a7a635cb"
}
}
}
Attendess collection view to view people who attend
import UIKit
import Firebase
import FirebaseStorage
class AttendeesCollectionViewController: UIViewController , UICollectionViewDelegateFlowLayout, UICollectionViewDataSource {
var posts = [Events]()
#IBOutlet weak var CVAttendee: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.navigationBar.barTintColor = UIColor(red: 0, green: 128.0/255.0, blue: 64.0/255.0, alpha: 1.0)
self.navigationController?.navigationBar.tintColor = UIColor.white
self.navigationController?.navigationBar.titleTextAttributes = [NSForegroundColorAttributeName: UIColor.white]
// Do any additional setup after loading the view.
fetchEvents()
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let height: CGFloat = view.frame.size.height
let width: CGFloat = view.frame.size.width
return CGSize(width: CGFloat(width * 0.95), height: CGFloat(height * 0.75))
}
override func viewDidAppear(_ animated: Bool) {
self.tabBarController?.tabBar.isHidden = false
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.posts.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "UserCell", for: indexPath) as! AttendeeCollectionViewCell
//Creating the cell
cell.lblFirstName.text = self.posts[indexPath.row].FirstName
cell.lblLastName.text = self.posts[indexPath.row].LastName
cell.lblNumberAttendee.text = self.posts[indexPath.row].Attend
if let imagePath = self.posts[indexPath.row].userPic{
cell.imgUser.downloadImage(from: imagePath)
}
else{
cell.imgUser.image = UIImage(named: "abstract-user-flat-4")
}
cell.EventId = self.posts[indexPath.row].EventId
cell.lblEmail.text = self.posts[indexPath.row].Email
cell.lblPhoneNum.text = self.posts[indexPath.row].PhoneNumber
return cell
}
func fetchEvents(){
let dbRef = Database.database().reference()
dbRef.child("Attendee").queryOrdered(byChild: "EventId").observeSingleEvent(of: .value, with: { (snapshot) in
let postData = snapshot.value as! [String: AnyObject]
for(_ ,value ) in postData{
let event = Events()
if
let FirstName = value["UserFirstName"] as? String,
let LastName = value["UserLastName"] as? String,
let Email = value["Email"] as? String,
let PhoneNumber = value["PhoneNumber"] as? String,
let attendingID = value["attendingID"] as? String, // let NumberAttend = value["Event date End"] as? String,
let pathToImage = value["pathToImage"] as? String,
let EventId = value["EventId"] as? String,
let userId = value["userId"] as? String {
event.FirstName = FirstName
event.LastName = LastName
event.Email = Email
event.PhoneNumber = PhoneNumber
event.pathToImage = pathToImage
// event.dateStart = NumberAttend
event.EventId = EventId
event.userId = userId
event.attendingID = attendingID
dbRef.child("users").queryOrderedByKey().observeSingleEvent(of: .value, with: { (snap) in
let users = snap.value as! [String: AnyObject]
for(_ ,userVal) in users {
if let uid = userVal["uid"] as? String{
if uid == userId{
if let img = userVal["urlToImage"] as? String{
event.userPic = img
}
}
}
}
})
dbRef.child("Attendee").observe(.value, with: { (snap) in
// post.commentCount = Int(arc4random_uniform(UInt32(snap.childrenCount)))
let comments = snap.value as! NSDictionary
for key in (comments.allKeys) {
if key as! String == attendingID{
let attendee = comments.value(forKey: attendingID) as! NSDictionary
if let attending = attendee.value(forKey: "Attendees"){
let attending = attending as? NSDictionary
// event.commentCount = messages?.count
}
else{
// event.commentCount = 0
}
self.CVAttendee.reloadData()
}
}
})
self.posts.append(event)
}
}
})
dbRef.removeAllObservers()
}
}
Events class
import UIKit
import Firebase
class Events: NSObject {
var author: String!
var Email: String!
var likes: Int!
var Attend : String!
var commentId: String!
var attendingID : String!
var pathToImage: String!
var userId: String!
var userPic: String!
var EventId: String!
var dateStart: String!
var dateEnd: String!
var desc: String!
var Category: String!
var Fee: String!
var EventTitle: String!
var commentCount: Int!
var SponsorPakage : String!
var locationAddress: NSDictionary!
var peopleWhoLike: [String] = [String]()
var peopleWhoattend: [String] = [String]()
var FirstName: String!
var LastName: String!
var PhoneNumber : String!
var go: goingStatus!
}
Firebase picture
post child firebase database shootscreen
user child firebase shootscreen