Подтвердить что ты не робот

Как вы называете вариационный метод Objective-C от Swift?

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

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

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

MyClassName.executeUpdateQuery("")

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

4b9b3361

Ответ 1

Напишите версию 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]))

Добавьте расширение для поддержки собственных переменных Variable Variable:

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)

Ответ 2

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) }
}

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

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

Обратите внимание также, что этот пример не использует getVaList, потому что docs говорит, что это "лучший избегать".

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

Ответ 3

В 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 - добавить в свой класс Отлично работает

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]