How to call an Objective-C function with a (NSMutableArray *)parameter in Swift?

I need to use an Objective-C class in Swift wuith some functions that have NSMutableArray * parameter, as the following example:


@interface StereotacticFrame : NSObject


- (BOOL)sortFiducials :(NSMutableArray *)fiducials :(float)imageWidth;

....


Where fiducials is an in-out parameter.


In Swift class I have the property

var fiducials = NSMutableArray(capacity: 9)

I need to use the Obj-C class like this:


let frame = StereotacticFrame()

frame.sortFiducials(&fiducials, Float(imageView.bounds.size.width))


But I got the following error: '&' used with non-inout argument of type 'NSMutableArray!'


This class perform some complex medical calculations and could be very difficult for me to translate to Swift the whole thing.

What I can do?


Thanks in advance!


PS.: If the & is removed, the program crashes when de function is executed, because "fiducials" is actually an in-out parameter!

If I understand well how this works, your objc sortFiducials is imported in Swift as :


func sortFiducials(_ array: fiducials!, imageWidth: Float) -> Bool


then it should be called as

frame.sortFiducials(fiducials, Float(imageView.bounds.size.width))


See OOPer (credit to him) answer here:

h ttps://stackoverflow.com/questions/41274950/swift-method-contain-nsmutablearray-doest-override

I did a test without the &:

frame.sortFiducials(fiducials, Float(imageView.bounds.size.width))


The program crashes when the function is executed, because "fiducials" is actually an in-out parameter.


It seems that the function is imported assuming that fiducials is not an in-out parameter.


Then, when the Obj-C function tries to change the content of the array, the app crashes.

Have you checked you have no inconsistency between framework and Swift code ?

Can you recompile the framwork ?

Parameters of type

NSMutableArray
don’t get any Swift magic; the importer imports them as
NSMutableArray
. Such arrays are mutable, meaning that the caller can mutate them and you see the results. So, while they can act as in/out parameters they don’t need to be imported into Swift as
inout
parameters, so there’s no ampersand (
&
) at the call site.

For example, a class like this:

NS_ASSUME_NONNULL_BEGIN

@interface Test : NSObject

- (void)addObject:(id)object toList:(NSMutableArray *)list;

@end

NS_ASSUME_NONNULL_END

is imported in Swift as:

open class Test : NSObject {
    open func add(_ object: Any, toList list: NSMutableArray)
}

and thus you can call it from Swift as:

let t = Test()
let list = NSMutableArray()
list.add("hello")
t.add("cruel", toList: list)
list.add("world")
NSLog("%@", list)

and get output like this:

2018-05-10 13:05:05.259166+0100 xxst[41284:14867763] (
    hello,
    cruel,
    world
)

To investigate this further I recommend that you create a small test project and implement a dummy version of this method in Objective-C and then call it from Swift via a bridging header. That will eliminate the possibility of a header/implementation mismatch, as suggested by Claude31.

If your test project still crashes then you can post snippets of it so that we can see the actual code.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"
How to call an Objective-C function with a (NSMutableArray *)parameter in Swift?
 
 
Q