harry lakins harry lakins - 11 months ago 68
iOS Question

How to match the 2d array datatype between swift and objective-c?

I am calling a .mm (objective-c / c++) class method from my swift viewController via linked headers. They are successfully linked. However, I am struggling to pass correct data types that match as parameters.
Here is where I call the function in swift

OpenCVWrapper.thefunc(array1, otherstuff);

is of type

and here is the definition in objective-c

+(NSString*) thefunc: (int[][2])array1 otherstuff(int)other{

but i get the error

Cannot convert value of type '[[Int]]' to expected argument type 'UnsafeMutablepointer<(Int32)(Int32)>!'

My question is, how can I match the data types so they both handle a basic 2D array of type Int?


value / structure issues:

structure passed from swift:

enter image description here

structure received in OC:

enter image description here

Answer Source

First of all, you may need to know that C-array and Swift Array are different things. C-array represents a contiguous region of memory and uses the pointer to the first element when passed.

Second, if you want to use imported Objective-C method from Swift, you'd better check the generated header of the method.

(Press the "four square icon" and choose "Generated Interface" while editor is showing the .h file.)

Tested with a small sample project, your method is imported as:

open class func thefunc(_ array1: UnsafeMutablePointer<(Int32, Int32)>!, otherstuff other: Int32) -> String!

(The corresponding type to int in Swift is Int32, not Int.)

So, you may need to pass a mutable pointer to tuple (Int32, Int32), to do that you need to declare a Swift Array of Element type (Int32, Int32) and pass it as an inout argument (using &).

So, you may need to write something like this:

//Assuming all inner Array of `array1` have two elements.
var convertedArray = array1.map {(Int32($0[0]), Int32($0[1]))}
MyClass.thefunc(&convertedArray, otherstuff: someInt32Value)

But the conversion of huge array may take some amount of time, in some cases, which is critical.

You may declare your Swift side array1 as Array of (Int32, Int32) and modify other parts according to this change, and use it as:

//Somewhere in your code...
var array1: [(Int32, Int32)] = []


//And call `thefunc` as:
MyClass.thefunc(&array1, otherstuff: someInt32Value)