Вы обнаружили любопытную «особенность» форматирования в Objective-C и должны посетить Помощник Apple по обратной связи и сообщить об этом.
Так что же происходит? Ну, это вообще не имеет ничего общего с функциями вариации, и не имеет ничего общего с NSLogv
как таковым . Скорее это связано с базовым кодом форматирования Objective C, который NSLog
, NSLogv
, stringWithFormat:
, и др. использует и тип самой строки форматирования. ..
Вот простая демонстрация «функции»:
- (void)demo
{
char *sample = "АБВГ"; // This will be UTF-8 encoded
// use %p to show address, %s to show string, \n as printf doesn't add one
char *cFormat = "%p - %s\n";
NSString *nsFormat = @"%p - %s\n"; // produces an __NSCFConstantString
NSString *convertedFormat = [NSString stringWithUTF8String:cFormat]; // produces an __NSCFString
printf(cFormat, sample, sample); // works
NSLog(convertedFormat, sample, sample); // fails with __NSCFString
NSLog(nsFormat, sample, sample); // works with __NSCFConstantString
NSLog(@"formats equal: %s", [convertedFormat isEqualToString:nsFormat] ? "yes" : "no"); // __NSCFString & __NSCFConstantString are equal
}
Запустите это, и консоль покажет что-то вроде:
0x1000013f8 - АБВГ
2019-10-01 10:25:48.222537+0100 demo[8435:1431874] 0x1000013f8 - –ê–ë–í–ì
2019-10-01 10:25:48.222560+0100 demo[8435:1431874] 0x1000013f8 - АБВГ
2019-10-01 10:25:48.222582+0100 demo[8435:1431874] formats equal: yes
Итак, Cбиблиотека printf
работает, NSLog
с константой NSString
работает, но NSLog
с NSString
форматом, преобразованным из char *
, не работает, и все же последние два формата сравниваются одинаково... Обратите также внимание, что в случае ошибки NSLog
добавляет дополнительную новую строку.
Плохой вывод –ê–ë–í–ì
- это та же интерпретация строки аргумента, которую Xcode показывает для байтов памяти строки. Таким образом, базовый тип строки format определяет, как интерпретируются базовые байты строки аргумента ...
Такая странная «особенность» заставляет задуматьсябыл ли это разработан по какой-то причине, или мы упускаем очевидное ... Может быть, кто-то еще может просветить нас, но если они этого не сделают, давайте назовем это (любопытно) ошибкой!
Обходной путь
Как показывает вышеприведенная демонстрация использования функций формата библиотеки C, так что если вы довольны потерей преамбулы NSLog
на каждом наброске, вы можете просто использовать одну из них вваша функция:
void MyLog(const char *format, ...)
{
va_list vargs;
va_start(vargs, format);
vprintf(format, vargs);
va_end(vargs);
}
Если вы хотите сохранить NSLog
для вывода, вы можете использовать один из эквивалентов библиотеки C stringWithFormat:
, вот версия вашей функции, которая динамически распределяет необходимыеместо для отформатированной строки C, а затем освободите ее (ARC не сделает этого за вас!):
void MyLog(const char *format, ...)
{
va_list vargs;
va_start(vargs, format);
char *output;
vasprintf(&output, format, vargs);
NSLog(@"%s", output);
free(output);
va_end(vargs);
}
«Функция» все еще существует в последней версии Xcode 11 и macOS Catalina Beta, поэтому, пожалуйста, сделайте этоотправьте сообщение об этом в Помощник Apple по обратной связи .
HTH