Search code examples
swiftios8nsvaluecllocationcoordinate2d

NSValue to CLLocationCoordinate2D in Swift


I am using Contentful.com as a content-backend for my iOS app. I can not get their geo-point return to work for me in my Swift project.

The Contentful documentation says their API returns "NSData with CLLocationCoordinate2D struct."

I am approaching this with NSValue in my project, but I can not get it to work properly. Here's my code:

var locationCoord:CLLocationCoordinate2D = CLLocationCoordinate2D(latitude: 0,longitude: 0)

var locationData:NSData = entry.fields["location"] as NSData

var locationValue:NSValue = NSValue(bytes: locationData.bytes, objCType: "CLLocationCoordinate2D")

locationCoord = locationValue.MKCoordinateValue

However, locationCoord.latitude and locationCoord.longitude return wrong values (one of them always being 0.0).

Can someone tell me what I am doing wrong here, and how to make this work properly? Thanks.


Solution

  • I think, getBytes:length: from NSData would be sufficient:

    var locationData = entry.fields["location"] as NSData
    var locationCoord = CLLocationCoordinate2D(latitude: 0, longitude: 0)
    locationData.getBytes(&locationCoord, length: sizeof(CLLocationCoordinate2D))
    

    BTW, Why your code doen't work?

    That is: objCType: parameter is not expecting a type name "String", but expecting "Type Encodings", in this case that is {?=dd}. In Objective-C, you have handy @encode(TypeName), but not in Swift. The easiest way to get that is to use .objCType property of NSValue.

    var locationData = entry.fields["location"] as NSData
    var locationCoord = CLLocationCoordinate2D(latitude: 0, longitude: 0)
    var objCType = NSValue(MKCoordinate: locationCoord).objCType // <- THIS IS IT
    var locationValue = NSValue(bytes: locationData.bytes, objCType: objCType)
    locationCoord = locationValue.MKCoordinateValue
    

    Moreover, It seems CDAEntry in Contentful SDK has the exact API, I think you should use this:

    /**
     Retrieve the value of a specific Field as a `CLLocationCoordinate2D` for easy interaction with
     CoreLocation or MapKit.
    
     @param identifier  The `sys.id` of the Field which should be queried.
     @return The actual location value of the Field.
     @exception NSIllegalArgumentException If the specified Field is not of type Location.
     */
    -(CLLocationCoordinate2D)CLLocationCoordinate2DFromFieldWithIdentifier:(NSString*)identifier;