Ответ 1
Краткая версия:
Я думаю, что это происходит, если последовательность UTF-8 выхода NSLog()
падает на границу буфера
псевдотерминала, который Xcode использует для стандартной ошибки отлаженного процесса.
Если мое предположение верно, это только проблема вывода отладчика Xcode и не подразумевает никаких проблем с Unicode в приложении.
Длинная версия:
Если вы запустите свое приложение в симуляторе, lsof -p <pid_of_simulated_app>
показывает, что стандартный
ошибка (файловый дескриптор 2) перенаправляется на псевдотерминал:
# lsof -p 3251
...
testplay 3251 martin 2w CHR 16,2 0t131 905 /dev/ttys002
...
И lsof -p <pid_of_Xcode>
показывает, что Xcode имеет тот же псевдотерминал open:
# lsof -p 3202
...
Xcode 3202 martin 51u CHR 16,2 0t0 905 /dev/ttys002
...
NSLog()
записывается в стандартную ошибку. С помощью индикатора системного вызова "dtruss" можно видеть
что Xcode считывает сообщение журнала с псевдотерминала. Для одного сообщения журнала
NSLog(@"⊢ ⊣ ⊥ ⊻ ⊼ ⊂ ⊃ ⊑ ⊒ \n");
он выглядит так:
# dtruss -n Xcode -t read_nocancel
3202/0xe101: read_nocancel(0x31, "2013-02-05 08:57:44.744 testplay[3251:11303] \342\212\242 \342\212\243 ... \342\212\222 \n\0", 0x8000) = 82 0
Но для многих операторов NSLog()
, следующих друг за другом быстро, иногда происходит следующее:
# dtruss -n Xcode -t read_nocancel
...
3202/0xd828: read_nocancel(0x33, "2013-02-05 08:39:51.156 ...", 0x8000) = 1024 0
3202/0xd87b: read_nocancel(0x33, "\212\273 \342\212\274 ...", 0x8000) = 24 0
Как вы можете видеть, Xcode прочитал 1024 байта из псевдотерминала, а следующее прочитанное начинается с неполной последовательности UTF-8. В этом случае Xcode "не видит", что последний байт первого считывания и первые два байта второго чтения являются частями такой же последовательности UTF-8. Я предполагаю, что Xcode обрабатывает все 3 байта как недопустимые последовательности UTF-8 и печатает их как восьмеричные числа.