Jordi Gámez
Jordi Gámez

Reputation: 3544

Map not reading code first time in Swift2 iOS9

I'm trying to display some shops in my map and it's working fine (the second time the user go to that MapViewController, but the first time (when it's asking for the user permission location) it only displays the user location and the map is not "zoomed" in the user location.

I'm going to show my code, it's very straightforward and simple:

Updated with the new code (it's still not working and the "didChangeAuthorizationStatus" is not printing anything:

import UIKit
import MapKit

class MapViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {

let LoadURL = "http://www.website.es/shops.json"

var coordinates = CLLocation()

@IBOutlet weak var mapView:MKMapView!

var farmacia = [Farmacia]()

let locationManager = CLLocationManager()

var currentLocation = CLLocation()

var latitudeValor = String()

var longitudeValor = String()

override func viewDidLoad() {

    super.viewDidLoad()

    locationManager.delegate = self

    // Request for a user's authorization for location services
    locationManager.requestWhenInUseAuthorization()

    if CLLocationManager.locationServicesEnabled() {
        locationManager.startUpdatingLocation()
        requestLocation()
    }
}

func requestLocation () {

    let status = CLLocationManager.authorizationStatus()

    if status == CLAuthorizationStatus.AuthorizedWhenInUse || status == CLAuthorizationStatus.AuthorizedAlways {
        self.mapView.showsUserLocation = true

        var currentLocation = CLLocation()

        print(locationManager.location)

        if locationManager.location != nil
        {
            currentLocation = locationManager.location!
            let center = CLLocationCoordinate2D(latitude: currentLocation.coordinate.latitude, longitude: currentLocation.coordinate.longitude)
            let region = MKCoordinateRegion(center: center, span: MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01))

            latitudeValor = String(currentLocation.coordinate.latitude)
            longitudeValor = String(currentLocation.coordinate.longitude)

            self.mapView.setRegion(region, animated: true)

            requestPost()

            mapView.delegate = self
        }
    }
}

func locationManager(locationManager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus) {

    switch status {

        case .NotDetermined:
            self.locationManager.requestWhenInUseAuthorization()
            break
        case .AuthorizedWhenInUse:
            self.locationManager.startUpdatingLocation()
            requestLocation()
            break
        case .AuthorizedAlways:
            self.locationManager.startUpdatingLocation()
            requestLocation()
            break
        case .Restricted:
            // restricted by e.g. parental controls. User can't enable Location Services
            break
        case .Denied:
            // user denied your app access to Location Services, but can grant access from Settings.app
            break
    }
}

/*
func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) {

    let location = locations.last as! CLLocation

    let center = CLLocationCoordinate2D(latitude: location.coordinate.latitude, longitude: location.coordinate.longitude)

    let region = MKCoordinateRegion(center: center, span: MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01))

    self.mapView.setRegion(region, animated: true)

    requestPost()

    mapView.delegate = self
}
*/

func requestPost () {

    let myUrl = NSURL(string: "http://www.website.es/shops_by_position.php");

    let request = NSMutableURLRequest(URL:myUrl!);
    request.HTTPMethod = "POST"

    let postString = "latitude="+latitudeValor+"&longitude="+longitudeValor
    request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)

    let session = NSURLSession.sharedSession()

    let task = session.dataTaskWithRequest(request) { (data:NSData?, response:NSURLResponse?, error:NSError?) -> Void in

        // JSON RESULTADO ENTERO
        //let responseString = NSString(data: data!, encoding: NSUTF8StringEncoding)!
        //print("responseString = \(responseString)")

        if error != nil
        {
            //print("error=\(error)")
            return
        }
        else
        {
            self.farmacia = self.parseJsonData(data!)
        }
    }

    task.resume()
}

func parseJsonData(data: NSData) -> [Farmacia] {

    let farmacias = [Farmacia]()

    do {
        let jsonResult = try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers) as? NSDictionary

        // Parse JSON data
        let jsonProductos = jsonResult?["farmacias"] as! [AnyObject]

        //print(jsonProductos)

        for jsonProducto in jsonProductos {

            let farmacia = Farmacia()
            farmacia.id = jsonProducto["id"] as! String
            farmacia.nombre = jsonProducto["nombre"] as! String

            farmacia.latitude = jsonProducto["latitude"] as! String
            farmacia.longitude = jsonProducto["longitude"] as! String

            let stringLat = NSString(string: farmacia.latitude)
            let stringLon = NSString(string: farmacia.longitude)

            let latitude: CLLocationDegrees = stringLat.doubleValue
            let longitude: CLLocationDegrees = stringLon.doubleValue

            coordinates = CLLocation(latitude: latitude,longitude: longitude)

            let geoCoder = CLGeocoder()

            geoCoder.reverseGeocodeLocation(coordinates, completionHandler: { placemarks, error in

                if error != nil
                {
                    //print(error)
                    return
                }
                else
                {
                    if placemarks != nil && placemarks!.count > 0 {

                        let placemark = placemarks?[0]

                        // Add Annotation
                        let annotation = MKPointAnnotation()
                        annotation.title = farmacia.nombre
                        annotation.coordinate = placemark!.location!.coordinate

                        self.mapView.addAnnotation(annotation)
                    }

                }

            })
        }
    }
    catch let parseError {
        print(parseError)
    }

    return farmacias
}

func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {

    let identifier = "MyPin"

    if annotation.isKindOfClass(MKUserLocation) {
        return nil
    }

    let detailButton: UIButton = UIButton(type: UIButtonType.DetailDisclosure)

    // Reuse the annotation if possible
    var annotationView = mapView.dequeueReusableAnnotationViewWithIdentifier(identifier)

    if annotationView == nil
    {
        annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: "pin")
        annotationView!.canShowCallout = true
        annotationView!.image = UIImage(named: "pin.png")
        annotationView!.rightCalloutAccessoryView = detailButton
    }
    else
    {
        annotationView!.annotation = annotation
    }

    return annotationView
}

func mapView(mapView: MKMapView, annotationView: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {

    if control == annotationView.rightCalloutAccessoryView {
        performSegueWithIdentifier("PinDetail2", sender: annotationView)
    }
}

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
    if segue.identifier == "PinDetail" {
        let destinationController = segue.destinationViewController as! FarmaciaDetailViewController
        destinationController.titulo_farmacia = (sender as! MKAnnotationView).annotation!.title!
    }
    if segue.identifier == "PinDetail2" {
        let destinationController = segue.destinationViewController as! FarmaciaWebDetailViewController
        destinationController.nombre_farmacia = (sender as! MKAnnotationView).annotation!.title!
    }
}

@IBAction func cancelToMap(segue:UIStoryboardSegue) {

}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}
}

My question is: What I have to change in order to show the user location zoomed and my shop entries the first time the app asks for permission and the user choose "Yes"?

It's my first time using the MapKit framework and I'm a little bit lost, so much appreciated if you can show me some light in my case.

Upvotes: 0

Views: 230

Answers (2)

Kosuke Ogawa
Kosuke Ogawa

Reputation: 7451

1) Change

class MapViewController: UIViewController, MKMapViewDelegate {

to

class MapViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {

2) Change

func locationManager(locationManager: CLLocationManager!, didChangeAuthorizationStatus status: CLAuthorizationStatus) {

switch status {

    case .NotDetermined:
        self.locationManager.requestAlwaysAuthorization()

to

        self.locationManager.requestWhenInUseAuthorization()

3) Add NSLocationWhenInUseUsageDescription to Info.plist

enter image description here

EDIT

4) Add the following code to viewDidLoad

locationManager.delegate = self

EDIT 2

5) Add import to header

import CoreLocation

Upvotes: 1

Морт
Морт

Reputation: 1179

The documentation for requestWhenInUseAuthorization says

When the current authorization status is kCLAuthorizationStatusNotDetermined, this method runs asynchronously and prompts the user to grant permission to the app to use location services.

So in your code, the authorisation is requested and then execution immediately continues, eventually reaching

if status == CLAuthorizationStatus.AuthorizedWhenInUse

which fails, at status is still not determined.

There is the locationManager:didChangeAuthorizationStatus: callback in CLLocationManagerDelegate that is called once the user allows or denies location access.

I would suggest that you move your logic for the .AuthorizedWhenInUse case in a function and call it either from your viewDidLoad method for cases when authorisation is already granted or from the callback if it is not granted yet.

Upvotes: 1

Related Questions