NSLog на устройствах в iOS 10 / Xcode 8 кажется усеченным? Причина?
5 59
5 ответов:
временное решение, просто пересмотреть все
NSLOG
toprintf
в глобальном заголовочном файле.#define NSLog(FORMAT, ...) printf("%s\n", [[NSString stringWithFormat:FORMAT, ##__VA_ARGS__] UTF8String]);
в iOS 10 и Xcode 8 Apple переключилась с старого доброго
ASL
(системный журнал Apple) в новую систему ведения журнала под названиемUnified logging
.NSLog
вызовы фактически делегируя новыйos_log
API. (источник:https://developer.apple.com/reference/os/logging):важно
единое ведение журнала доступно в iOS 10.0 и более поздних версиях, macOS 10.12 и позже, tvOS 10.0 и позже, и watchOS 3.0 и позже, и заменяет ASL (системный регистратор Apple) и API системного журнала. Исторически журнал сообщения записывались в определенные места на диске, например системы /и т. д./.бревно. Единая система ведения журнала хранит сообщения в памяти и в хранилище данных, а не для записи в текстовые файлы журналов.
и
важно
строки сообщений журнала, превышающие максимальную длину сообщения системы, усекаются при хранении системой ведения журнала. Полные сообщения являются видимый при использовании инструмента командной строки журнала для просмотра живого потока деятельность. Однако имейте в виду, что потоковые данные журнала являются дорогостоящая деятельность.
ограничение "максимальная длина сообщения системы" показано в заголовке SDK, чтобы быть 1024 символов для форматированных переменных, как отмечено @Hot_Leaks (источник:
<os/log.h>
):/*! * @function os_log * * ... * * There is a physical cap of 1024 bytes per log line for dynamic content, * such as %s and %@, that can be written to the persistence store. * All content exceeding the limit will be truncated before it is * written to disk. * * ... * */ #define os_log(log, format, ...) os_log_with_type(log, OS_LOG_TYPE_DEFAULT, format, ##__VA_ARGS__)
поскольку ограничение размера буфера, похоже, жестко закодировано в
libsystem_trace.dylib
, Я не вижу пути вокруг него, но для печати строкового литерала вместо форматированной переменной (%@
), или разбить форматированные строковые переменные на
printf
будет работать во время отладки, так как отладчик (Xcode) показывает потоки out / error процесса, но он не будет отправлен в журнал самого устройства. Это означает, что решение xfdai не поможет вам при использовании других приложений журнала, таких как macOSConsole
приложение, или с проблемой, возникающей в не отлаженных приложениях (таких как Приложение AppStore работает на устройстве клиента).
расширение ответа xfdai на развернутые приложения
в развернутых приложений / не-отладочные построения, нет никакого способа, чтобы увидеть, как
NSLog
илиprintf
s.единственный способ печати сообщений непосредственно в журнал устройств (доступ к которому можно получить с помощью Xcode - > Window - > Devices, консольного приложения mac или сторонних утилит, таких как deviceconsole) является звоню
os_log
API (который является преемникомASL
используется с iOS 10).вот глобальный файл заголовка, который я использую для переопределения
NSLog
как позвонить_os_log_internal
на iOS 10:#ifndef PrefixHeader_pch #define PrefixHeader_pch #ifdef __OBJC__ #import <UIKit/UIKit.h> #import <Foundation/Foundation.h> #endif #import <os/object.h> #import <os/activity.h> /* * System Versioning Preprocessor Macros */ #define SYSTEM_VERSION_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedSame) #define SYSTEM_VERSION_GREATER_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedDescending) #define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending) #define SYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending) #define SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedDescending) // os_log is only supported when compiling with Xcode 8. // Check if iOS version > 10 and the _os_log_internal symbol exists, // load it dynamically and call it. // Definitions extracted from #import <os/log.h> #if OS_OBJECT_SWIFT3 OS_OBJECT_DECL_SWIFT(os_log); #elif OS_OBJECT_USE_OBJC OS_OBJECT_DECL(os_log); #else typedef struct os_log_s *os_log_t; #endif /* OS_OBJECT_USE_OBJC */ extern struct os_log_s _os_log_default; extern __attribute__((weak)) void _os_log_internal(void *dso, os_log_t log, int type, const char *message, ...); // In iOS 10 NSLog only shows in device log when debugging from Xcode: #define NSLog(FORMAT, ...) \ if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"10.0")) {\ void(*ptr_os_log_internal)(void *, __strong os_log_t, int, const char *, ...) = _os_log_internal;\ if (ptr_os_log_internal != NULL) {\ _Pragma("clang diagnostic push")\ _Pragma("clang diagnostic error \"-Wformat\"")\ _os_log_internal(&__dso_handle, OS_OBJECT_GLOBAL_OBJECT(os_log_t, _os_log_default), 0x00, [[NSString stringWithFormat:FORMAT, ##__VA_ARGS__] UTF8String]);\ _Pragma("clang diagnostic pop")\ } else {\ NSLog(FORMAT, ##__VA_ARGS__);\ }\ } else {\ NSLog(FORMAT, ##__VA_ARGS__);\ } #endif /* PrefixHeader_pch */
на iOS 10:
printf()
работает внутри консоли Xcode, но не работает в журнале консоли устройства.NSLog
усекает в обоих местах.то, что я сейчас делаю, это расщепление моего
NSLog
строки в строки и протоколирование каждой строки по отдельности.- (void) logString: (NSString *) string { for (NSString *line in [string componentsSeparatedByCharactersInSet: [NSCharacterSet newlineCharacterSet]]) { NSLog(@"%@", line); } }
это работает в консоли, но не легко читать.
вы можете использовать этот метод. Разделите каждые 800 символов. Или может быть установлен. NSLOG я думаю усечь каждые 1000 символов. Если строка меньше 800 будет использовать простой NSLog. Это полезно для длинных строк JSON и использует консоль. printf использует окно отладки Xcode, а не консоль.
-(void) JSLog:(NSString*)logString{ int stepLog = 800; NSInteger strLen = [@([logString length]) integerValue]; NSInteger countInt = strLen / stepLog; if (strLen > stepLog) { for (int i=1; i <= countInt; i++) { NSString *character = [logString substringWithRange:NSMakeRange((i*stepLog)-stepLog, stepLog)]; NSLog(@"%@", character); } NSString *character = [logString substringWithRange:NSMakeRange((countInt*stepLog), strLen-(countInt*stepLog))]; NSLog(@"%@", character); } else { NSLog(@"%@", logString); } }