Convert UnsafeMutablePointer<CLLocationCoordinate2D> to [CLLocationCoordinate2D] in Swift - ios

I write an app in Swift and is bridging some Objective-C code. One of these classes has a method that looks like this: + (CLLocationCoordinate2D *)polylineWithEncodedString:(NSString *)encodedString;.
In Swift, it said this method returns a UnsafeMutablePointer<CLLocationCoordinate2D>. What I want is a Swift array of CLLocationCoordinate2D.
What obviously doesn't work, but I tried, is this:
let coordinates: [CLLocationCoordinate2D] = TheClass.polylineWithEncodedString(encodedString)
which will give me the following error:
'UnsafeMutablePointer<CLLocationCoordinate2D>' is not convertible to '[CLLocationCoordinate2D]'
Is it somehow possible to convert this UnsafeMutablePointer<CLLocationCoordinate2D> to a [CLLocationCoordinate2D]? Or should I take a different approach?

You can just use the memory property of the UnsafeMutablePointer, which is the data behind the pointer. But keep in mind that UnsafeMutablePointer < CLLocationCoordinate2D > will return one CLLocationCoordinate2D, not an array, just as declared in the obj c function.
var coordinate: CLLocationCoordinate2D = TheClass.polylineWithEncodedString(encodedString).memory

Related

Contextual Type AnyObject Cannot Be Used With Array Literal for Coordinates

I have look into several other different questions posted with the same problem but non of them help answer my question because I am using this for coordinates. I recently upgrade to Swift3 and I got this error "Contextual Type AnyObject Cannot Be Used With Array Literal"
So this is how the code looks like where I declare my variable for my coordinates
var coordinates: [AnyObject]!
This is the next code where the error occurs, I will replace the numbers with x. I am using the longitude and latitude
coordinates = [[xx.xxxxxx, -xxx.xxxxxx],[xx.xxxxxx, -xxx.xxxxxx],[xx.xxxxxx, -xxx.xxxxxx]]
And the way I call it is by using for loop which I dont think causes any problem but I'll just post it just in case
for i in 0...2
{
let coordinate = coordinates[i]}
Problem solved by implementing
var coordinates: [[Double]]!
Just change :-
import MapKit
class yourController : ...{
var coordinates: [AnyObject]!
To
var coordinates = [CLLocationCoordinate2D]()
To access a particular lat or long at a particular index just:-
coordinates[your_index].latitude // Latitude
coordinates[your_index].longitude //Longitude
CLLocationCoordinate2D is a struct , much more easily scalable and accessible than array.

UnsafeMutablePointer for array using in C library

I want to implement C library into my iOS project. I'm using swift language.
I have a function where the input parameter - where output values are stored - is ar usual C double array:
double ar[6];
///...
err = c_lib_func(ar);
If I initialize inside swift like var ar: [Double] xCode says I have to use
UnsafeMutablePointer. But inside the docs I haven't found how to initialize n-lenght array for UnsafeMutablePointer. I just can do something like this:
var ar : UnsafeMutablePointer<Double>. But I can understand how to initialize it as 6-length array. Please, help me.
If I'm using
ar = [Double]
err = c_lib_func(ar);
the xCode shows to me this error:
/Users/admin/Documents/projects/myApp/myApp/file.swift:46:46: Cannot
convert value of type '[Double]' to expected argument type
'UnsafeMutablePointer'
In Swift, [Double] is an array of double values which is not what you are after. If you want to initialize an UnsafeMutablePointer you can just use:
var ar = UnsafeMutablePointer<Double>.alloc(6)
Use ar.dealloc(6) to release the memory again.

Unknown swift property in obj-c class

I have declare a property var coordinate:CLLocationCoordinate2D? in my swift class
but i can't find this property in obj-c class. I have tried to add #obj before the class, but it doesn't work.
You can not access the instance variable because coordinate:CLLocationCoordinate2D is not bridged with Objective C. Instead of declaring CLLocationCoordinate2D, you can declare latitude and longitude as NSNumber type and later using them make 2D coordinate.
var lat: NSNumber?
var lon: NSNumber?
And then assign value in your Objc Class as bellow:
switObject.lat = #3;
switObject.lon = #5;
For more information check this link Cannot access property of Swift type from Objective-C
The problem is that you have declared an optional property (?), which is a pure Swift construct. They cannot be accessed by Objective C classes unless specifically bridged, like String -> NSString.
Obj-C doesn't support optional structs. But if you make it non-optional, it compiles:
import CoreLocation
class Class : NSObject
{
dynamic var coordinate:CLLocationCoordinate2D // no `?`: non-optional
override init()
{
coordinate = CLLocationCoordinate2D() // it's not optional, so you must initialize `coordinate`
}
}

annoying parameter error for polylineWithCoordinates

I am trying to initialize a polyline from a 2 element CLLocationCoordinate2D array called coordarray and the number 2, using this code:
self.line = MKPolyline.polylineWithCoordinates(coordarray,2)
however I am getting an error saying
Cannot invoke 'polylineWithCoordinates' with an argument list of type
([CLLocationCoordinate2D],Int)
I have checked the docs, and it seems that I have passed the correct parameter list, what am I missing?
That error message is very misleading - checking the documentation for MKPolyline there isn't actually a static method called polylineWithCoordinates for Swift, you may be looking at the Objective-C version of the documentation*. Perhaps you meant to use:
convenience init!(coordinates coords: UnsafeMutablePointer<CLLocationCoordinate2D>,
count count: Int)
In which case I believe your code needs to be:
// Note - coordarray is declared as var
var coordarray = // ...
self.line = MKPolyline(coordinates: &coordarray, count: 2)
Here's a link detailing more about adding an MKPolyline overlay: http://mobiletoolworks.com/adding-a-mkpolyline-overlay-using-swift-to-an-ios-mapkit-map/
*To change the documentation from displaying Objective-C to Swift, there's a control in the top-right corner of the page:

Optional dynamic properties in Swift

I'm attempting to compile the following Swift class:
class Waypoint: NSObject {
dynamic var coordinate: CLLocationCoordinate2D?
}
But I get the following compiler error:
Property cannot be marked dynamic because its type cannot be represented in Objective-C
If I change coordinate to be non-optional everything works just fine. I suppose this makes sense, since Objective-C has no concept of optionals. Is there any known solution or workaround?
In Objective-C, you can use nil to signal the absence of value, but only on object types. Swift generalizes this (and makes it type-safe) with the Optional generic type: you can have an Optional<NSObject>, a.k.a. NSObject?, but you can also have an Int? or a CLLocationCoordinate2D?.
But CLLocationCoordinate2D is a struct — if you use it in Objective-C, you can't assign nil to a variable of type CLLocationCoordinate2D. This is why you get this error.
As for an (ugly) workaround, you could wrap CLLocationCoordinate2D in a object:
class CLLocationCoordinate2DObj: NSObject {
let val: CLLocationCoordinate2D
init(_ val: CLLocationCoordinate2D) {
self.val = val
}
}
class Waypoint: NSObject {
dynamic var coordinate: CLLocationCoordinate2DObj?
}
Unfortunately, you can't find a more general solution with a generic object wrapper class for structs, as Objective-C doesn't have generics… An alternative would be to use NSValue as object type as described here, but I doubt that it would be more elegant.

Resources