When I add the annotations to the map they sometimes show and sometimes not depending on how close they are to each other. If they are in the same house lets say one won't show. How do I make both of them show? Do I need to make a custom annotation class? I heard ios11 has a clumping feature, do I need to use that? Here is the code(abridged):
import UIKit
import MapKit
import Firebase
class GameViewController: UIViewController {
@IBOutlet weak var mapView: MKMapView!
fileprivate var locations = [CLLocation]()
fileprivate var userLocations = [(loc: CLLocation, name: String, team: String)]()
fileprivate var userAnnotations = [MKAnnotation]()
fileprivate var hasBeenUP = false
var ref: FIRDatabaseReference!
let uid = FIRAuth.auth()!.currentUser!.uid
var timer = Timer()
var timeLeft = 0.0
var firstTimer = Timer()
var name = ""
var team = ""
override func viewDidLoad() {
super.viewDidLoad()
let center = CLLocationCoordinate2D(latitude: 47.786769, longitude: -20.413634)
let region = MKCoordinateRegion(center: center, span: MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01))
self.mapView.setRegion(region, animated: true)
mapView.mapType = .hybrid
locationManager.startUpdatingLocation()
ref = FIRDatabase.database().reference()
setupULSending()
getMetaInfo()
ref.child("realtimeLocations").observe(FIRDataEventType.value, with: { (snapshot) in
self.userLocations = []
for rest in snapshot.children.allObjects as! [FIRDataSnapshot] {
guard let snapshotValue = snapshot.value as? NSDictionary, let snapVal = snapshotValue[rest.key] as? NSDictionary else {
break
}
let name = snapVal["name"] as! String
let team = snapVal["team"] as? String ?? ""
if let lat = snapVal["lat"] as? Double,
let long = snapVal["long"] as? Double {
let location = CLLocation(latitude: lat, longitude: long)
self.userLocations.append((loc: location, name: name, team: team))
}else {
}
}
DispatchQueue.main.async {
self.updateUserLocation()
}
})
}
private lazy var locationManager: CLLocationManager = {
let manager = CLLocationManager()
manager.allowsBackgroundLocationUpdates = true
manager.desiredAccuracy = kCLLocationAccuracyBest
manager.delegate = self
manager.requestAlwaysAuthorization()
return manager
}()
func updateUserLocation() {
for an in self.mapView.annotations {
mapView.removeAnnotation(an)
}
for loc in userLocations {
let annotation = MKPointAnnotation()
annotation.coordinate = loc.loc.coordinate
annotation.title = loc.name
annotation.subtitle = "local"
mapView.addAnnotation(annotation)
}
}
}
// MARK: - CLLocationManagerDelegate
extension GameViewController: CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didUpdateLocations
locations: [CLLocation]) {
let location = locations.last as! CLLocation
self.locations.append(location)
}
}
On the MKAnnotationView, you have to set the MKFeatureDisplayPriority to 'required'. You can modify the annotation views by implementing MKMapViewDelegate and mapView(MKMapView, viewFor: MKAnnotation)
. Something like this:
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation { return nil }
var view = mapView.dequeueReusableAnnotationView(withIdentifier: "yourIdentifier")
if view == nil {
view = MKMarkerAnnotationView(annotation: nil, reuseIdentifier: "yourIdentifier")
}
view?.displayPriority = .required
return view
}
More options for this are explained in the WWDC 2017 video 237 "What's New in MapKit"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With