9

this is my code.getting this EXC_BAD_ACCESS(code=EXC_i386_GPFLT).I don'n know how to find and solve plz help me ...application getting crash when get longitude

mapServerRequest="Hyderabad,india"
var mapAddress:NSString=mapServerRequest
mapAddress.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLPathAllowedCharacterSet())
     println(mapAddress)
var urlpath=NSString(format: "http://maps.googleapis.com/maps/api/geocode/json?address=%@", mapAddress)
     println(urlpath)
var url = NSURL.URLWithString(urlpath)
    println(url)
var jsonData:NSData=NSData(contentsOfURL:url)

       if(jsonData != nil)
    {
        var error:NSError=NSError(coder: nil)
        var result:NSDictionary=NSJSONSerialization .JSONObjectWithData(jsonData, options: NSJSONReadingOptions.MutableContainers, error: nil) as NSDictionary
        //println(result)
        if (error != nil)
        {
            mapServerResultArray=result.valueForKey("results") as NSMutableArray
           // println(mapServerResultArray)

        }
      var longitud:NSString

           longitud=mapServerResultArray.objectAtIndex(0).valueForKey("geometry").valueForKey("location").valueForKey("lng")as NSString

        var latitud :NSString = (mapServerResultArray .objectAtIndex(0).valueForKey("geometry").valueForKey("location").valueForKey("lat")) as NSString
        placeName=mapServerResultArray .objectAtIndex(0).valueForKey("formatted_address") as NSString
        var longitude:Float=longitud.floatValue
        var latitude:Float=latitud.floatValue
        self.zoomMapAndCenterAtLatitude(latitude)
        self.zoomMapAndCenterAtLongitud(longitude) 
user3541467
  • 1,693
  • 3
  • 12
  • 6

5 Answers5

9

Short answer:

enable Zombies in the Scheme and it will enable a breakpoint and proper reason will be displayed in the logs

Technical reason:

You are trying to do something which in not allowed in the architecture refer this What's the meaning of exception code "EXC_I386_GPFLT"?

Community
  • 1
  • 1
Ankit Sachan
  • 7,690
  • 16
  • 63
  • 98
  • 3
    For those wondering how to "enable Zombies" here's an answer that has you covered: https://stackoverflow.com/a/20534105/6749410 – HirdayGupta Aug 06 '18 at 19:39
3

Your problem here is that most of the operations you are performing can return nil, which will crash Swift if you try and use it as a non-nil value. You need to be explicit about testing for nil. The sledgehammer way of doing it would be

let mapAddress = "Hyderabad,india"

let url = NSURL.URLWithString("http://maps.googleapis.com/maps/api/geocode/json?address=\(mapAddress)")

let jsonData = NSData(contentsOfURL:url)

var latitude = NSNumber(double: 0.0)
var longitude = NSNumber(double: 0.0)
var success = false

if jsonData != nil {
    if let result = NSJSONSerialization.JSONObjectWithData(jsonData, options: NSJSONReadingOptions.MutableContainers, error: nil) as? NSDictionary {
        if let mapServerResultArray = result.valueForKey("results") as? NSArray {
            if let geometry = mapServerResultArray[0].valueForKey("geometry") as? NSDictionary {
                if let location = geometry.valueForKey("location") as? NSDictionary {
                    if let lat = location.valueForKey("lat") as? Float {
                        latitude = lat
                        if let lng = location.valueForKey("lng") as? Float {
                            longitude = lng
                            success = true
                        }
                    }
                }
            }
        }
    }
}
if success {
    println("Latitude = \(latitude), longitude=\(longitude)")
} else {
    println("Failed")
}

... however that is ugly. As this routine may or may not find any of the keys, at the end you may or may not have a valid pair of coordinates. This is exactly what Optionals are for. Consider rewriting it as a function that returns an optional:

struct Coordinate { // Or use any of Cocoa's similar structs
    var latitude: Double
    var longitude: Double
}

func getCoordsOf(#address: String) -> Coordinate? {
    let url = NSURL.URLWithString("http://maps.googleapis.com/maps/api/geocode/json?address=\(address)")
    let jsonData = NSData(contentsOfURL:url)
    if jsonData == nil { return nil }

    let result = NSJSONSerialization.JSONObjectWithData(jsonData, options: NSJSONReadingOptions.MutableContainers, error: nil) as NSDictionary
    if result == nil { return nil }

    if let geometry = result.valueForKey("results").valueForKey("geometry") as? NSArray {
        if geometry.count > 0 {
            let lat = geometry[0].valueForKey("location")?.valueForKey("lat")?.doubleValue
            let lng = geometry[0].valueForKey("location")?.valueForKey("lng")?.doubleValue

            if (lat != nil) && (lng != nil) {
                return Coordinate(latitude: lat!, longitude: lng!)
            }
        }
    }
    return nil
}

if let coord = getCoordsOf(address: "Hyderabad,india") {
    // ... do something
}

This uses Optional Chaining (?) to lessen the testing, but we have to break it at geometry because we need that to be an array, as we need to access a specific element of it (and, of course, should test that it isn't an empty array!)

p.s. - ironically, your test on error != nil does nothing, as you did not send error to the JSONObjectWithData routine.

Grimxn
  • 22,115
  • 10
  • 72
  • 85
  • Should that last line be let coord? = ... as the func can return nil? – Peter Aug 22 '14 at 13:47
  • 1
    It's not typed, so I guess I could claim `coord` is a `Coordinate?`, but, as far as my intentions were concerned, you are correct!!! Answer changed. – Grimxn Aug 22 '14 at 14:42
1

In that type of situation you can convert latitude to string. Updated code:

 mapServerRequest="Hyderabad,india"
    var mapAddress:NSString=mapServerRequest
    mapAddress.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLPathAllowedCharacterSet())
         println(mapAddress)
    var urlpath=NSString(format: "http://maps.googleapis.com/maps/api/geocode/json?address=%@", mapAddress)
         println(urlpath)
    var url = NSURL.URLWithString(urlpath)
        println(url)
    var jsonData:NSData=NSData(contentsOfURL:url)

           if(jsonData != nil)
        {
            var error:NSError=NSError(coder: nil)
            var result:NSDictionary=NSJSONSerialization .JSONObjectWithData(jsonData, options: NSJSONReadingOptions.MutableContainers, error: nil) as NSDictionary
            //println(result)
            if (error != nil)
            {
                mapServerResultArray=result.valueForKey("results") as NSMutableArray
               // println(mapServerResultArray)

            }
          var longitud:NSString

               longitud=NSString(format:mapServerResultArray.objectAtIndex(0).valueForKey("geometry").valueForKey("location").valueForKey("lng"))
            var latitud :NSString
 latitud=NSString(format:(mapServerResultArray .objectAtIndex(0).valueForKey("geometry").valueForKey("location").valueForKey("lat")))
            placeName=NSString(format:mapServerResultArray .objectAtIndex(0).valueForKey("formatted_address"))
            var longitude:Float=longitud.floatValue
            var latitude:Float=latitud.floatValue
            self.zoomMapAndCenterAtLatitude(latitude)
            self.zoomMapAndCenterAtLongitud(longitude)
saraman
  • 568
  • 7
  • 19
-4

This response you are getting :"http://maps.googleapis.com/maps/api/geocode/json?address=Hyderabad,india"

You can fetch like below:

Here jsondict is your respnse from api

NSArray *results = [jsonDict objectForKey:@"results"];    
NSDictionary *geometry = [[results objectAtIndex:0] valueForKey:@"geometry"];
NSArray *location = [geometry objectForKey:@"location"];
float lat = [[location valueForKey:@"lat"] floatValue];    
float lng = [[location valueForKey:@"lng"] floatValue];
Sviatoslav Yakymiv
  • 7,887
  • 2
  • 23
  • 43
-5

use this :

var longitud:NSString =(mapServerResultArray.objectAtIndex(0).valueForKey("geometry").objectForKey("location").valueForKey("lng")) as NSString

var latitud :NSString = 
(mapServerResultArray .objectAtIndex(0).valueForKey("geometry").objectForKey("location").valueForKey("lat")) as NSString
        placeName=mapServerResultArray .objectAtIndex(0).valueForKey("formatted_address") as NSString
        var longitude:Float=longitud.floatValue
        var latitude:Float=latitud.floatValue
        self.zoomMapAndCenterAtLatitude(latitude)
        self.zoomMapAndCenterAtLongitud(longitude) 
Sviatoslav Yakymiv
  • 7,887
  • 2
  • 23
  • 43
  • That's going to fail horribly if any of those keys aren't there. You need to test for nil. – Grimxn Jul 19 '14 at 09:42
  • This response coming from google api. this will change by google. we can't change. So we have to prevent also horribly fail or crashing issue through conditions like you have given answer. – Kinjal Dhagat Jul 20 '14 at 17:12