Как вы называете вариационный метод Objective-C от Swift?
Предположим, что у меня есть класс в Objective-c со статическим методом, подобным этому:
+ (NSError *)executeUpdateQuery:(NSString *)query, ...;
Как мне позвонить из Swift? Автозаполнение не распознает его, и компилятор недоволен:
MyClassName.executeUpdateQuery("")
Жалуется, что "MyClassName.Type не имеет члена с именем executeUpdateQuery"
Ответы
Ответ 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]