你如何从Swift调用Objective-C可变方法?

时间:2014-06-13 00:04:33

标签: objective-c swift variadic-functions

假设我在Objective-c中有一个类,其静态方法如下:

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

如何从Swift中调用它?自动完成功能无法识别它,编译器对以下内容不满意:

MyClassName.executeUpdateQuery("")

抱怨' MyClassName.Type没有名为executeUpdateQuery的成员'

3 个答案:

答案 0 :(得分:46)

编写variadic方法的va_list版本;

+ (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;
}

然后可以从Swift

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

添加扩展名以支持本机Swift可变参数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)

小心,Swift没有提供NS_FORMAT_FUNCTION警告(-Wformat)

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

答案 1 :(得分:5)

  

CVArgType在本地呈现C“varargs”API时非常有用   迅速。 (Swift Docs)

如果你有

+ (int)f1:(int)n, ...;

首先需要制作va_list版本:

+ (int)f2:(int)n withArguments:(va_list)arguments

可以通过从可变参数版本调用va_list版本来完成without duplicating code。如果您没有编写原始的可变参数函数,则可能无法实现(在this reference中解释)。

一旦你有了这个方法,就可以编写这个Swift包装器:

func swiftF1(x: Int, _ arguments: CVarArgType...) -> Int {
     return withVaList(arguments) { YourClassName.f2(x, withArguments :$0) }
}

注意省略的外部参数名称_之前的arguments),这使得swiftF1的调用语法就像普通的C变量函数一样:< / p>

swiftF1(2, some, "other", arguments)

注意此示例也不使用getVaList,因为docs表示“最好避免使用”。

如果需要,您可以进一步将此函数放在原始类的Swift扩展中。

答案 2 :(得分:1)

目标C

MyClassName.h

+ (BOOL)executeSQL:(NSString *)sql args:(va_list)args;

MyClassName.m

+ (BOOL)executeSQL:(NSString *)sql args:(va_list)arguments
{
    NSLogv(sql, arguments);

    sql = [[NSString alloc] initWithFormat:sql arguments:arguments];
    va_end(arguments);
}

Swift - 在课堂上添加 完美无缺

protocol CFormatFunction {
   class func executeSQLArg(format: String, _ args: CVarArgType...) -> Bool
}

extension MyClassName : CFormatFunction {
   class func executeSQLArg(format: String, _ args: CVarArgType...) -> Bool
   {
        return MyClassName(format, args:getVaList(args))
   }
 }

如何使用

夫特

MyClassName.executeSQLArg(query, "one","two",3)

目标C

[MyClassName executeSQLArg:query, @"one",@"two",@3]