ribl / FBAnnotationClusteringSwift

Swift translation of FB Annotation Clustering, which clusters pins on the map for iOS.
http://ribl.co/blog/2015/05/28/map-clustering-with-swift-how-we-implemented-it-into-the-ribl-ios-app/
MIT License
311 stars 109 forks source link

How to set default location to current? #9

Closed Deepak050392 closed 8 years ago

Deepak050392 commented 8 years ago

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.

chenr2 commented 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:

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().

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)")
    }
}
    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...
    }
//mapView.centerCoordinate = CLLocationCoordinate2DMake(0, 0);

Hope this helps. Rob

Deepak050392 commented 8 years ago

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)

chenr2 commented 8 years ago

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:

extension FBViewController : CLLocationManagerDelegate {
//...
}
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.

Deepak050392 commented 8 years ago

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)

chenr2 commented 8 years ago

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?

Deepak050392 commented 8 years ago

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.

chenr2 commented 8 years ago

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)
    }
}
Deepak050392 commented 8 years ago

simulator screen shot 21-dec-2015 11 41 06 pm

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.

chenr2 commented 8 years ago

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.

Deepak050392 commented 8 years ago

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

Deepak050392 commented 8 years ago

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.

chenr2 commented 8 years ago

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.