答案 0 :(得分:69)
临时解决方案,只需在全局头文件中重新定义所有NSLOG
到printf
。
#define NSLog(FORMAT, ...) printf("%s\n", [[NSString stringWithFormat:FORMAT, ##__VA_ARGS__] UTF8String]);
答案 1 :(得分:38)
在iOS 10& Xcode 8,Apple从好的旧ASL
(Apple系统日志)切换到名为Unified logging
的新日志系统。实际上,NSLog
次来电已委托给os_log
新API <os/log.h>
。 (来源:https://developer.apple.com/reference/os/logging):
重要强>
统一日志记录在iOS 10.0及更高版本,macOS 10.12和 之后,tvOS 10.0及更高版本,以及watchOS 3.0及更高版本,并取代 ASL(Apple System Logger)和Syslog API。从历史上看,日志 消息被写入磁盘上的特定位置,例如 /etc/system.log。统一日志记录系统将消息存储在内存中 并且在数据存储中,而不是写入基于文本的日志文件。
和
重要强>
日志消息行大于系统的最大消息长度在日志记录系统存储时被截断。完整的消息是 使用日志命令行工具查看实时流时可见 活动。但请记住,流式日志数据是一个 昂贵的活动。
&#34;系统的最大消息长度&#34;如@Hot_Leaks(来源:/*!
* @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__)
所述),SDK标题中的限制显示为格式化变量的1024个字符:
libsystem_trace.dylib
由于缓冲区大小限制似乎硬编码到%@
中,我看不到它的方法,但打印字符串文字而不是格式化变量(printf
) ,或将格式化的字符串变量拆分为&lt; 1024个字符串。
Console
将在调试期间工作,因为调试器(Xcode)显示进程的输出/错误流,但它不会被发送到设备日志本身。这意味着xfdai的解决方案在使用其他日志应用程序(如macOS的NSLog
应用程序)时,或者在未调试的应用程序(例如AppStore应用程序)上出现问题时无法帮助您在客户的设备上运行。
扩展xfdai对已部署应用程序的回答
在已部署的应用程序/非调试版本中,无法查看printf
或os_log
s。
将消息直接打印到设备日志的唯一方法(可以使用Xcode - &gt; Window - &gt;设备,mac的控制台应用程序或第三方实用程序,例如deviceconsole)进行访问正在调用ASL
API(这是自iOS 10以来NSLog
使用的继承者)。
这是我用来在iOS 10上重新定义_os_log_internal
作为对#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 */
的调用的全局标题文件:
if (Double.IsNaN(YourValue) || Double.IsInfinity(YourValue))
{
YourValue = 0;
}
答案 2 :(得分:9)
它只是iOS 10&#34;功能&#34;。请改用:
printf("%s", [logString UTF8String]);
答案 3 :(得分:2)
在iOS 10上:
printf()
在Xcode的控制台中运行,但不能在设备的控制台日志中运行。 NSLog
会在这两个地方截断。我现在正在做的是将我的NSLog
字符串拆分成行并分别记录每一行。
- (void) logString: (NSString *) string
{
for (NSString *line in [string componentsSeparatedByCharactersInSet: [NSCharacterSet newlineCharacterSet]])
{
NSLog(@"%@", line);
}
}
这适用于控制台,但不易阅读。
答案 4 :(得分:2)
您可以使用此方法。每800个字符分开。或者可以设置。 NSLOG我认为截断每1000个字符。 如果string小于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);
}
}
答案 5 :(得分:0)
这不能提供很好的输出,但是即使在控制台上,也可以打印长日志的所有必要信息。
func Log(_ logString: String?) {
if logString?.isEmpty ?? false { return }
NSLog("%@", logString!)
Log(String(logString!.dropFirst(1024)))
}
答案 6 :(得分:0)
从@xfdai答案中添加漂亮的功能和线条
#define NSLog(FORMAT, ...) printf("%s:%d %s\n", __PRETTY_FUNCTION__,__LINE__,[[NSString stringWithFormat:FORMAT, ##__VA_ARGS__] UTF8String])
带日期
#define NSLog(FORMAT, ...) printf("%s %s:%d %s\n", [[[NSDate date] description] UTF8String],__PRETTY_FUNCTION__,__LINE__,[[NSString stringWithFormat:FORMAT, ##__VA_ARGS__] UTF8String])