/*!
* @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__)
extension String {
/// Splits the string into chunks to accommodate a specified maximum length,
/// considering line breaks as the preferred splitting points.
///
/// - Parameters:
/// - maxLength: The maximum length of each output chunk. The default value is 1000.
/// - Returns: An array of `Substring` chunks.
///
/// - Note: The function iterates through the original string and creates chunks of text
/// based on the specified maximum length. If a line break character is found
/// within the chunk, the split occurs at the line break. If no line break
/// character is present, the function tries to split at the last space character
/// before the maxLength. If no space is found, the chunk is split at the
/// maxLength. The line break character or space character (if used for
/// splitting) is dropped from the output.
///
/// - Complexity: The time complexity is O(n), where n is the number of characters
/// in the string. The function iterates through the string once to create the
/// chunks.
public func splittedForLogger(maxLength: Int = 1000) -> [Substring] {
var chunks: [Substring] = []
var currentIndex = self.startIndex
while currentIndex < self.endIndex {
let remainingLength = self.distance(from: currentIndex, to: self.endIndex)
let chunkLength = min(maxLength, remainingLength)
let nextIndex = self.index(currentIndex, offsetBy: chunkLength)
let chunk = self[currentIndex..<nextIndex]
if chunkLength == remainingLength {
/// Last chunk
chunks.append(chunk)
break
}
/// Attempt to find the last line break character within the chunk
/// If not found, attempt to find the last space character
/// If neither line break nor space character is found, split at the maxLength
let splitIndex = chunk.lastIndex { character in
CharacterSet.newlines.contains(character.unicodeScalars.first ?? .init(0))
} ?? chunk.lastIndex { character in
CharacterSet.whitespaces.contains(character.unicodeScalars.first ?? .init(0))
} ?? chunk.endIndex
let splitChunk = self[currentIndex..<splitIndex]
chunks.append(splitChunk)
currentIndex = splitIndex < chunk.endIndex ? self.index(after: splitIndex) : nextIndex
}
return chunks
}
@inlinable public func forEachLoggerChunk(
maxLength: Int = 1000,
_ body: (Substring) throws -> Void
) rethrows {
try self
.splittedForLogger(maxLength: maxLength)
.forEach(body)
}
}
8条答案
按热度按时间deikduxw1#
一个临时的解决方案,只是在一个全局头文件中将所有的
NSLOG
重新定义为printf
。字符串
bweufnob2#
在iOS 10和Xcode 8中,苹果从旧的
ASL
(苹果系统日志)切换到一个名为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 System Logger)和Syslog API。历史上,日志消息被写入磁盘上的特定位置,例如/etc/system. log。统一日志记录系统将消息存储在内存和数据存储中,而不是写入基于文本的日志文件。
还有
重要
日志记录系统存储时,将截断大于系统最大消息长度的日志消息行。使用log命令行工具查看实时活动流时,完整的消息是可见的。但是,请记住,流式日志数据是一项昂贵的活动。
正如@Hot_Leaks所指出的那样,SDK的头文件中显示的“系统最大消息长度”限制为格式化变量的1024个字符(来源:
<os/log.h>
):字符串
由于缓冲区大小限制似乎是硬编码到
libsystem_trace.dylib
中的,所以我看不到解决方法,只能打印字符串字面量而不是格式化变量(%@
),或者将格式化字符串变量拆分为< 1024个字符串。printf
将在调试期间工作,因为调试器(Xcode)显示进程的out / error流,但它不会被发送到设备日志本身。这意味着xfdai的解决方案在使用其他日志应用程序(如macOS的Console
应用程序)或未调试应用程序(如客户设备上运行的AppStore应用程序)出现问题时无法帮助您。将xfdai的解决方案扩展到已部署的应用程序
在部署的应用程序/非调试版本中,无法看到
NSLog
或printf
。将消息直接打印到设备日志(可以使用Xcode -> Window -> Devices,mac的Console App或第三方实用程序(如deviceconsole)访问)的唯一方法是调用
os_log
API(这是自iOS 10以来使用的ASL
的继承者)。下面是一个全局头文件,我使用它将
NSLog
重新定义为iOS 10上对_os_log_internal
的调用:型
x759pob23#
这是iOS 10唯一的“功能”。使用这个代替:
字符串
nwsw7zdq4#
可以使用此方法。每800个字符拆分一次。或者可以设定。NSLOG我认为每1000个字符截断一次。如果string小于800将使用简单的NSLog。这对于Json长字符串很有用,并使用控制台。printf使用Xcode调试窗口而不是控制台。
字符串
siv3szwd5#
在iOS 10上:
printf()
在Xcode的控制台内工作,但在设备的控制台日志上不工作。NSLog
在两个位置都截断。我现在要做的是将
NSLog
字符串拆分成几行,并分别记录每一行。字符串
这在控制台上工作,但不容易阅读。
00jrzges6#
漂亮的功能和线条
字符串
带日期
型
改进@xfdai答案
qco9c6ql7#
这并没有提供一个很好的输出,但是打印了长日志的所有必要信息,甚至在控制台上也是如此。
字符串
aor9mmx18#
下面是我的Swift解决同样问题的方法。我遇到了这个1000~1024字符的限制,每个插值符号。
由于我在记录
json
文件时经常遇到这种情况,所以我决定将字符串拆分成块,但不是直接拆分。我尝试在换行符处进行拆分,以保留多个日志之间的整个json
字符串。所提供的解决方法背后的另一个原因是将
logger.debug(_:)
调用保持在原来的位置,这样我就不会失去访问实际记录它的源代码位置的能力。所以我的解决方案是:
字符串
现在你可以像这样使用它来记录长字符串。你只要改变你的
型
变成这样
型
测试结果:
x1c 0d1x的数据