How do you call an Objective-C variadic method from Swift?

rustyshelf picture rustyshelf · Jun 13, 2014 · Viewed 11k times · Source

Supposing I have a class in Objective-c with a static method like this:

+ (NSError *)executeUpdateQuery:(NSString *)query, ...;

How do I call that from Swift? The autocomplete doesn't recognise it, and the compiler is unhappy with:

MyClassName.executeUpdateQuery("")

Complaining that 'MyClassName.Type does not have a member named executeUpdateQuery'

Answer

Simon picture Simon · Jun 13, 2014

Write a va_list version of your variadic method;

+ (NSError *)executeUpdateQuery:(NSString *)query, ...
{
    va_list argp;
    va_start(argp, query);
    NSError *error = [MyClassName executeUpdateQuery: query args:argp];
    va_end(argp);

    return error;
}

+ (NSError *)executeUpdateQuery:(NSString *)query args:(va_list)args
{
    NSLogv(query,args);
    return nil;
}

This can then be called from Swift

MyClassName.executeUpdateQuery("query %d, %d %d", args: getVaList([1,2,3,4]))

Add an extension to support native Swift variadic args:

protocol CFormatFunction {
    class func executeUpdateQuery(format: String, _ args: CVarArg...) -> NSError?
}

extension MyClassName : CFormatFunction {
    class func executeUpdateQuery(format: String, _ args: CVarArg...) -> NSError?
    {
        return MyClassName.executeUpdateQuery(format, args:getVaList(args))
    }
}

MyClassName.executeUpdateQuery("query %d %@ %.2f", 99, "Hello", 3.145)

Be careful, Swift doesn't provide NS_FORMAT_FUNCTION warnings (-Wformat)

MyClassName.executeUpdateQuery("query %@", 99)