-1

My app has two tabs. On the first tab a bunch of tab annotations are created based on an attraction. When you click on the annotation view, it goes to the 2nd tab which is a detail view controller of the attraction. I am wondering how I can pass the location of the attraction to the detailVC that way I can have the pin at the same address. Here is what I have so far, and there are some inconsistencies, as the address displayed on the detail vc is not equal to the address of the attraction.

func performSearch(input:String) {

        attractionsMap.removeAnnotations(attractionsMap.annotations);

        matchingItems.removeAll()

        let request = MKLocalSearchRequest()
        request.naturalLanguageQuery = input
        println(input);
        request.region = attractionsMap.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)")

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

                    var placemark = item.placemark;
                    var subThoroughfare:String = "";
                    var thoroughfare:String = "";
                    var locality:String = "";
                    var postalCode:String = "";
                    var administrativeArea:String = "";
                    var country:String = "";
                    var title = "";
                    var subtitle = "";

                    if (placemark.subThoroughfare != nil) {
                        subThoroughfare = placemark.subThoroughfare;
                    }
                    if(placemark.thoroughfare != nil) {
                        thoroughfare = placemark.thoroughfare;
                    }
                    if(placemark.locality != nil) {
                        locality = placemark.locality;
                    }
                    if(placemark.postalCode != nil) {
                        postalCode = placemark.postalCode;
                    }
                    if(placemark.administrativeArea != nil) {
                        administrativeArea = placemark.administrativeArea;
                    }
                    if(placemark.country != nil) {
                        country = placemark.country;
                    }
                    println("viewcontroller placmark data:");
                    println(locality);
                    println(postalCode);
                    println(administrativeArea);
                    println(country);

                    title = " \(subThoroughfare) \(thoroughfare) \n \(locality), \(administrativeArea) \n \(postalCode) \(country)";
                    subtitle = " \(subThoroughfare) \(thoroughfare)";
                    println(title);

                    var annotation = MKPointAnnotation()
                    annotation.coordinate = item.placemark.coordinate
                    annotation.title = item.name + " " + subtitle;
                    self.attractionsMap.addAnnotation(annotation)
                }
            }
        })
    }

This is the search and adding the pin annotations.

I then attempt to send the attractionLocation below

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        var attractionsDetailViewController:AttractionsDetailViewController = segue.destinationViewController as! AttractionsDetailViewController
        attractionsDetailViewController.attractionLocation = indicatedMapItem;
    }

And then my Detail ViewController to implement the given address:

func getInfo() {
    var latitude = attractionLocation.latitude;
    var longitude  = attractionLocation.longitude;
    var latDelta:CLLocationDegrees = 0.000001
    var longDelta: CLLocationDegrees = 0.000001
    var span: MKCoordinateSpan = MKCoordinateSpanMake(latDelta, longDelta);
    var location = CLLocationCoordinate2DMake(latitude, longitude);
    var realLocation = CLLocation(latitude: latitude, longitude: longitude);
    CLGeocoder().reverseGeocodeLocation(realLocation, completionHandler: { (placemarks, error) -> Void in
        var title = ""
        var subtitle = ""
        var locality = ""
        if(error == nil) {
            if let placemark = CLPlacemark(placemark: placemarks?[0] as! CLPlacemark) {
                var subThoroughfare:String = "";
                var thoroughfare:String = "";
                var locality:String = "";
                var postalCode:String = "";
                var administrativeArea:String = "";
                var country:String = "";

                if (placemark.subThoroughfare != nil) {
                    subThoroughfare = placemark.subThoroughfare;
                }
                if(placemark.thoroughfare != nil) {
                    thoroughfare = placemark.thoroughfare;
                }
                if(placemark.locality != nil) {
                    locality = placemark.locality;
                }
                if(placemark.postalCode != nil) {
                    postalCode = placemark.postalCode;
                }
                if(placemark.administrativeArea != nil) {
                    administrativeArea = placemark.administrativeArea;
                }
                if(placemark.country != nil) {
                    country = placemark.country;
                }
                println("viewcontroller placmark data:");
                println(locality);
                println(postalCode);
                println(administrativeArea);
                println(country);

                title = " \(subThoroughfare) \(thoroughfare) \n \(locality), \(administrativeArea) \n \(postalCode)\(country)";
                subtitle = " \(subThoroughfare) \(thoroughfare)";
                println(title);
                self.addressLabel.text = title;

            }
        }
        var overallLoc = CLLocationCoordinate2DMake(latitude, longitude);
        var region:MKCoordinateRegion = MKCoordinateRegionMake(overallLoc, span);
        var annotation = MKPointAnnotation();
        annotation.coordinate = location;
        annotation.title = subtitle;
        self.detailMap.addAnnotation(annotation);
        self.detailMap.setRegion(region, animated: true)
    })
}
Varun Varahabotla
  • 548
  • 2
  • 7
  • 16

2 Answers2

1

You can store a global variable, which is usually not recommended, or you can pass via segue, which is recommended. It's probably better to not reverse geocode again because reverse geocoding is not always the most accurate method of finding locations...

kebabTiger
  • 642
  • 7
  • 15
0

If you make your attractionLocation property in the detailsVC like this...

var attractionLocation: CLLocation?
var attractionAddress: String?

As far as I can tell, the getInfo function just needs to set the map's region and add the appropriate annotation. Seeing as the attractionLocation property will be a CLLocation we can access it's coordinate property. And if you pass through the attractionAddress from the first screen then CLGeocoder doesn't need to be used.

func getInfo() {

    // Create span for the map region
    var latDelta:CLLocationDegrees = 0.000001
    var longDelta: CLLocationDegrees = 0.000001
    var span: MKCoordinateSpan = MKCoordinateSpanMake(latDelta, longDelta);


    // Create region for map
    var region:MKCoordinateRegion = MKCoordinateRegionMake(attractionLocation!.coordinate, span);
    var annotation = MKPointAnnotation();
    annotation.coordinate = attractionLocation!.coordinate;
    annotation.title = attractionAddress!;
    self.detailMap.addAnnotation(annotation);
    self.detailMap.setRegion(region, animated: true)
}

In the past I've not found CLGeocoder to be that consistent when it comes to reverse geocoding. So at least this way you can be sure the address between the two screens will be consistent.

Rich
  • 882
  • 1
  • 8
  • 19