2016-12-05 2 views

ответ

7

Предположим, вы хотите написать функцию , аналогичную NSLog, но которая также сохраняет сообщение в массиве в дополнение к его регистрации. Как бы вы это реализовали?

Если вы пишете variadic functionvoid MySpecialLog(NSString *format, ...), кто-то может назвать вашу функцию так же, как NSLog - MySpecialLog(@"Hello %@!", name); - но единственный способ получить доступ дополнительные аргументы за format это с a va_list. В C или Obj-C нет splat operator, что позволяет передавать их непосредственно в NSLog внутри функции.

NSLogv решает эту проблему, принимая все дополнительные аргументы сразу через va_list. Его подпись: void NSLogv(NSString *format, va_list args). Вы можете использовать его для . Создайте свои собственные NSLog-обертки.

Obj-C

void MySpecialLog(NSString *format, ...) 
    NS_FORMAT_FUNCTION(1, 2) 
    // The NS_FORMAT_FUNCTION attribute tells the compiler to treat the 1st argument like 
    // a format string, with values starting from the 2nd argument. This way, you'll 
    // get the proper warnings if format specifiers and arguments don't match. 
{ 
    va_list args; 
    va_start(args, format); 

    // Do something slightly more interesting than just passing format & args through... 
    NSString *newFormat = [@"You've called MySpecialLog()! " stringByAppendingString:format]; 

    NSLogv(newFormat, args); 

    va_end(args); 
} 

Вы можете даже использовать ту же технику, чтобы обернуть NSLog с помощью метода Obj-C. (А поскольку -[NSString initWithFormat:] имеет подобный вариант под названием -initWithFormat:arguments:, вы можете обернуть его тоже.)

- (void)log:(NSString *)format, ... NS_FORMAT_FUNCTION(1, 2) 
{ 
    // Similarly to the above, we can pass all the arguments to -initWithFormat:arguments:. 
    va_list args; 
    va_start(args, format); 
    NSString *message = [[NSString alloc] initWithFormat:format arguments:args]; 
    va_end(args); 

    // Why not both? 
    va_start(args, format); 
    NSLogv(format, args); 
    va_end(args); 
} 

Swift

В Swift, вы можете сделать это с VARIADIC функция, принимающая CVarArg...:

func mySpecialLog(_ format: String, _ args: CVarArg...) { 
    withVaList(args) { 
     NSLogv("You've called mySpecialLog()! " + format, $0) 
    } 
} 
+0

Да, но я не понял, почему нам нужно использовать nslogv и его назначение – Sivagami

+0

Не должно быть * ...если у вас не было NSLog, ... "* в первой строке вашего первого примера кода? –

+0

Нет. Необходимо проиллюстрировать, что NSLogv необходим. – jtbandes

1

Вообще говоря, суффикс v означает, что функция принимает в качестве аргумента значение va_list, а не список вариационных аргументов.

Это случай для NSLog и NSLogv:

void NSLog(NSString *format, ...); 

void NSLogv(NSString *format, va_list args); 

Это полезно в некоторых очень специфических ситуациях, когда вам нужно «обернуть» функцию, которая принимает VARIADIC аргументы. Если вам это нужно, вы узнаете. В противном случае вы можете смело игнорировать его.

+0

Пожалуйста, объясните, что вам нужно «обернуть» функцию, которая принимает вариативные аргументы » –

1

NSLog - varadic function, что означает, что оно принимает переменное количество аргументов. Но иногда программисты захотят реализовать свою собственную функцию оболочки varadic, которая делает что-то еще до вызова NSLog.

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

Именно поэтому NSLogv существует отдельно от NSLog, который является просто оберткой, которая принимает переменное количество аргументов и передает их в NSLogv.

Смежные вопросы