Alec
Alec

Reputation: 213

Swift - Getting address from coordinates

I have a local search that creates annotations for each search result. I'm trying to add an call out accessory to each of the annotations, and once that will be pressed, the Maps app will open and set directions on how to get to the certain location.

The problem that I am having is that in order for the call out accessory to work correctly, you have to get the address using place marks in the Address Book import. I've done plenty of searching and can't figure out how to set it up correctly where I can covert the annotation coordinates into a kABPersonAddressStreetKey so the Maps app can read it correctly. Below is my code for the search function, and the open Maps app function.

func performSearch() -> MKMapItem {

    matchingItems.removeAll()
    let request = MKLocalSearchRequest()
    request.naturalLanguageQuery = searchText.text
    request.region = mapView.region

    let search = MKLocalSearch(request: request)

    search.startWithCompletionHandler({(response:
        MKLocalSearchResponse!,
        error: NSError!) in

        if error != nil {
            println("Error occured in search: \(error.localizedDescription)")
        } else if response.mapItems.count == 0 {
            println("No matches found")
        } else {
            println("Matches found")

            for item in response.mapItems as! [MKMapItem] {
                println("Name = \(item.name)")
                println("Phone = \(item.phoneNumber)")

                self.matchingItems.append(item as MKMapItem)
                println("Matching items = \(self.matchingItems.count)")

                var annotation = MKPointAnnotation()
                var coordinates = annotation.coordinate
                var location = CLLocation(latitude: annotation.coordinate.latitude, longitude: annotation.coordinate.longitude)
                var street = // Insert code here for getting address from coordinates
                var addressDictionary = [String(kABPersonAddressStreetKey): street]
                var placemark = MKPlacemark(coordinate: coordinates, addressDictionary: addressDictionary)
                var mapItem = MKMapItem(placemark: placemark)
                return mapItem

                annotation.coordinate = item.placemark.coordinate
                annotation.title = item.name
                self.mapView.addAnnotation(annotation)

            }
        }
    })
}


func mapView(mapView: MKMapView!, annotationView view: MKAnnotationView!,
    calloutAccessoryControlTapped control: UIControl!) {
        let location = view.annotation as! FirstViewController
        let launchOptions = [MKLaunchOptionsDirectionsModeKey: MKLaunchOptionsDirectionsModeDriving]
        location.performSearch().openInMapsWithLaunchOptions(launchOptions)
}

Any help would be greatly appreciated, thanks in advance.

Upvotes: 3

Views: 4177

Answers (1)

Duncan C
Duncan C

Reputation: 131398

Your assumption is wrong. You can generate a request for driving directions using lat/long coordinates just as easily as using addresses.

Here's what you do:

  1. Get the MKMapItem for the user-selected pin

  2. Create a second MKMapItem for the user's current location using the MKMapItem method mapItemForCurrentLocation().

  3. Call the MKMapItem class method openMapsWithItems() passing in the two MKMapItems for the current location and the destination, and a launchOptions dictionary specifying MKLaunchOptionsDirectionsModeDriving.

Edit:

Here's how you'd create a map item for the user-tapped item:

In your calloutAccessoryControlTapped method you get passed an annotation view. The MKAnnotationView class has an annotation property, an object that conforms to the MKAnnotation property.

An MKAnnotation object has a coordinate property.

You can fetch the annotation object from the annotation view, and the coordinate from the annotation object.

You would then take the coordinate and use it to create an MKPlacemark, using the initWithCoordinate:addressDictionary: method (passing in a nil addressDictionary).

That call might look like this:

let sourcePlacemark = MKPlacemark(
      coordinate: fromCoordinate,
      addressDictionary: nil)

You'd then take the place mark and use it to create an MKMapItem, using the initWithPlacemark: method.

Getting an MKMapItem for the user's current location:

There is a single MKMapView method, forCurrentLocation() that returns a MKMapItem for the current location.

Upvotes: 1

Related Questions