Как вы называете Variadic-метод Objective-C от Swift?

Предположим, что у меня есть class в Objective-c со статическим методом, подобным этому:

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

Как мне это назвать от Swift? Автозаполнение не распознает его, и компилятор недоволен:

 MyClassName.executeUpdateQuery("") 

Жалуясь, что «MyClassName.Type не имеет члена с именем executeUpdateQuery»

    Напишите версию вариационного метода 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:

     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) 

    CVArgType полезен при представлении API-интерфейсов C “varargs” изначально в Swift. (Swift Docs)

    Если у вас есть

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

    вам сначала нужно сделать версию va_list :

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

    Это можно сделать без дублирования кода , вызывая версию va_list из вариационной версии. Если вы не указали оригинальную вариационную функцию, это может быть невозможно (поясняется в этой ссылке ).

    Когда у вас есть этот метод, вы можете написать эту оболочку Swift:

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

    Обратите внимание на пропущенное имя внешнего параметра ( _ перед arguments ), что делает синтаксис вызова для swiftF1 точно так же, как нормальная вариационная функция C:

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

    Также обратите внимание, что этот пример не использует getVaList потому что документы говорят, что это «лучше всего избежать».

    Вы можете добавить эту функцию в расширение Swift исходного classа, если хотите.

    В objective 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 – добавить в свой class

     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) 

    Objetive C

     [MyClassName executeSQLArg:query, @"one",@"two",@3] 
    Давайте будем гением компьютера.