Closed Deepak050392 closed 8 years ago
Hi Deepak,
Obtaining the user's location is not within the scope of FBAnnotationClusteringSwift
. However, it just so happens that I'm in the middle of writing a MapKit related blog post at www.thorntech.com which includes a section on getting the user location. So I can give you a quick and dirty list of instructions right here:
Info.plist
, set NSLocationWhenInUseUsageDescription
as a String
to show the body copy the user will see in the permissions alert dialog. Without this, the user will never see the permissions alert.ViewController.swift
(or FBViewController.swift
in this repo), add the following code. This fires the permissions dialog (which you'll need on first launch) and the location request (which you'll need for subsequent launches).import UIKit
import MapKit
class ViewController : UIViewController {
let locationManager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters
locationManager.requestWhenInUseAuthorization()
locationManager.requestLocation()
}
}
Note: requestLocation()
is available in iOS 9. If you need to support iOS 8, there's a method startUpdatingLocation()
which is a little less elegant to use because you have to stop polling for location when location accuracy improvements start leveling off (otherwise, you'll drain the user's battery). Ray Wenderlich's iOS Apprentice (Part 3) has a very thorough user location section that covers startUpdatingLocation()
.
ViewController.swift
(outside of the class
body). This retries the location request if the user chose to Allow
location permissions. It also zooms in once it gets the user's location.extension ViewController : CLLocationManagerDelegate {
func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus) {
if status == .AuthorizedWhenInUse {
locationManager.requestLocation()
}
}
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
if let location = locations.first {
let region = MKCoordinateRegion(center: location.coordinate, span: span)
mapView.setRegion(region, animated: true)
}
}
func locationManager(manager: CLLocationManager, didFailWithError error: NSError) {
print("Error finding location: \(error.localizedDescription)")
}
}
Storyboard
, check the User Location
box in the Attributes Inspector
on the Map Kit View
. This shows the blue pulsy dot.ViewController.swift
, add this to the beginning of mapView(_:viewForAnnotation:)
. This makes sure the blue pulsy dot isn't affected by the pins/clusters. func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView?{
if annotation is MKUserLocation {
//return nil so map view draws "blue dot" for standard user location
return nil
}
// other code...
}
ViewController.swift
, make sure there's nothing else that would reposition the map. So comment this line out://mapView.centerCoordinate = CLLocationCoordinate2DMake(0, 0);
Hope this helps. Rob
Hi Rob, Thank You for your support. I hope it will work perfectly in the device. But I didn't get the current location. Because am using simulator. how could i set the latitude and longitude manually and test this in simulator. One more clarification needed other than current location i have to set the latitude and longitude for the map to locate or show the corresponding location.(but map automatically went to cluster view how could i avoid default cluster view)
You can set the simulator location. Within the Simulator application, go to Debug > Location > Custom Location... and enter in a longitude and latitude.
The simulator can sometimes still give an error when getting user location. I often have to quit the Simulator and then Build & Run again, and it usually works.
A few corrections to the code above:
FBViewController
, so this is the class/extension name that should be used:extension FBViewController : CLLocationManagerDelegate {
//...
}
span
variable declaration, but you can just use a MKCoordinateSpan
with an arbitrary 0.05 degrees.let span = MKCoordinateSpanMake(0.05, 0.05)
As for your last question regarding zooming to a default cluster view -- I'm not aware of any code in the library or example project that zooms to a location except for the line:
mapView.centerCoordinate = CLLocationCoordinate2DMake(0, 0);
You might want to try searching your project for centerCoordinate
or setRegion
to see if a delegate method is zooming to one of your clusters.
Thank you for your support. I have a trouble in Cluster. I dont know how to remove the annotation which i added in FBannoation.(Because if i reload the view the older cluster added to the new cluster and makes to heavy.) I searched no function for remove in FBannotation package. If there help me. And am try to set the location as
let center = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
let region = MKCoordinateRegion(center: center, span: MKCoordinateSpan(latitudeDelta: 0.002, longitudeDelta: 0.002))
mapView.setRegion(region, animated: true)
While there isn't a way to remove a specific annotation, you could use setAnnotations
which first clears the tree and then adds in the new annotations:
clusteringManager.setAnnotations(array)
As for your setRegion
code, where in your project are you calling this code? Is it in a delegate method? Or in viewDidLoad
? And are you still experiencing the issue where the map is zooming to the wrong spot?
Super, setAnnotations works great. Thank You so... much for your support, I used setRegion in the viewDidLoad, it points out the location correctly, but when i drag the map to other location it automatically came back to the setRegion location. i dont know why it happening. Then if i add new annotation am unable to show the added annotation's location directly. Instead it loads the viewDidLoad (current location) then it comes to the newly added location automatically.
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
var reuseId = ""
if annotation is MKUserLocation {
print("user location")
return nil
}
else if annotation.isKindOfClass(FBAnnotationCluster)
{
reuseId = "Cluster"
var clusterView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseId)
clusterView = FBAnnotationClusterView(annotation: annotation, reuseIdentifier: reuseId)
print("Cluster")
if ( isLongPressEnabled == true || iscurrentlocation == true)
{
print("inside cluster")
let center = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
let region = MKCoordinateRegion(center: center, span: spancoordinate)
mapView.setRegion(region, animated: true)
isregionchanged = true
}
return clusterView
}
else if annotation.isKindOfClass(MKPointAnnotation)
{
print("MKAnnotation")
let reuseId = "pin"
var pinnView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseId) as? MKPinAnnotationView
pinnView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
pinnView!.animatesDrop = true
return pinnView
}
else
{
reuseId = "Pin"
var pinView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseId)
pinView = MKAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
switch(selecteditem)
{
case 1:
imagename = "GreenDot"
case 2:
imagename = "GreenDot"
case 3:
imagename = "GreenDot"
case 4:
imagename = "GreenDot"
case 5:
imagename = "GreenDot"
case 6:
imagename = "GreenDot"
default:
imagename = "GreenDot"
}
pinView?.image = UIImage(named: imagename)
pinView?.draggable = true
print("Pin")
if( isLongPressEnabled == true || iscurrentlocation == true)
{
print("insidepin")
let center = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
let region = MKCoordinateRegion(center: center, span: spancoordinate)
mapView.setRegion(region, animated: true)
isregionchanged = true
}
return pinView
}
}
I have inserted the code sample. i have trouble in the setRegion.
You might consider deleting all of the setRegion
lines from your mapView(_:viewForAnnotation:)
method.
setRegion
might be more appropriate for a different delegate method mapView(_:didSelectAnnotationView:)
So maybe try something like this:
func mapView(mapView: MKMapView, didSelectAnnotationView view: MKAnnotationView) {
if let coordinate = view.annotation?.coordinate {
let span = MKCoordinateSpanMake(0.5, 0.5)
let region = MKCoordinateRegion(center: coordinate, span: span)
mapView.setRegion(region, animated: true)
}
}
1.I upload the image. i marked a new annotation in the memorial community hospital health system. But after adding new annotation it point the herman blvd(which i inserted as current location in my simulator), After that it zoom in and shows the memorial community hospital.
2.if i drag the map i cant able to drag map for other locations. but the map automatically returns to the mapsetRegion.
It's difficult for me to tell what's going on without looking at the code. If you have something posted on github, I can take a look and maybe help troubleshoot.
i sent the whole code here. i am trouble in moving the newly added annotation(which is add by own in post method to some url.)
how to click on to the cluster(cluster large,medium,small) circles to get in to zoom in. if i click on to the cluster it have to split into small clusters. but am unable to get this.
To answer your first question about the map zooming to different places after adding a new annotation, it's probably because savebuttonAction
is calling viewDidLoad
, which is usually not a good idea.
As for the question about map dragging, I'm having trouble getting the code to compile to reproduce the issue. There are references to other class files, and server calls with redacted URLs. Also, it seems these questions are related to your specific project rather than clustering manager questions that would benefit the larger iOS developer community.
And as for zooming into clusters, there was actually a separate issue that was raised for this. The verdict was that zooming in was not an ideal solution because there are plenty of times when two pins are on the exact same location and would remain a cluster at maximum zoom. Maybe an implementation where you displayed a table of annotation items found within that cluster would be more appropriate. Or you could try changing the span on didSelectAnnotationView
within your own code.
hi I am using this for clustering the locations, it works great, But i want to set the set location on loading the map. But it tends to full zoom out cluster view. i want how to set the initial location to current location and then i want to show the cluster only on zoom out and the zoom in.