Кто-нибудь может объяснить разницу между NSLog и NSLogv? Я знаю, что NSLog
используется для печати данных в консоли. Но что такое NSLogv
?
Разница между NSLog и NSLogv
Ответы:
Предположим, вы хотите написать функцию, похожую на NSLog, но которая помимо записи в журнал также сохраняет сообщение в массив. Как бы вы это реализовали?
Если вы напишете вариативную функцию void MySpecialLog(NSString *format, ...)
, кто-нибудь сможет вызвать вашу функцию точно так же, как NSLog — MySpecialLog(@"Hello %@!", name);
— но единственный способ получить доступ к дополнительным аргументам помимо format
— это использовать a va_list
. . Здесь нет оператора знака знака в C или Obj-C, что позволяет передавать их непосредственно в NSLog внутри функции.
NSLogv решает эту проблему, одновременно принимая все дополнительные аргументы через файл va_list
. Его подпись void NSLogv(NSString *format, va_list args)
. Вы можете использовать его для создания собственных оболочек NSLog.
Объект-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 вы можете сделать это с помощью функции с переменным числом аргументов, принимающей CVarArg...
:
func mySpecialLog(_ format: String, _ args: CVarArg...) {
withVaList(args) {
NSLogv("You've called mySpecialLog()! " + format, $0)
}
}
Вообще говоря, суффикс v
означает, что функция принимает va_list
в качестве аргумента, а не вариативный список аргументов.
void NSLog(NSString *format, ...);
void NSLogv(NSString *format, va_list args);
Это полезно в некоторых очень специфических ситуациях, когда вам нужно "обернуть" функцию, которая принимает аргументы с переменным числом аргументов. Если тебе это нужно, ты узнаешь. В противном случае вы можете смело игнорировать его.
NSLog
— это функция варадика, что означает, что она принимает переменное количество аргументов. Но иногда программисты хотят реализовать свою собственную функцию-оболочку varadic, которая делает что-то еще перед вызовом NSLog
.
Если бы NSLog
была единственной функцией, это было бы невозможно, потому что вы не можете передать набор varadic-аргументов (он же va_list
) другой varadic-функции.
Вот почему NSLogv
существует отдельно от NSLog
, который является просто оболочкой, которая принимает переменное количество аргументов и передает их NSLogv
.