调试器(或日志)中类似 NSDictionary 的漂亮打印

2024-01-06

这已经困扰我一段时间了。如何抵消在调试器中转储对象时发生的丑陋转义po foo(或通过NSLog)。我尝试了多种方法来实施-description or -debugDescription无济于事。

鉴于这个简单的类

@interface Foo : NSObject
@property NSDictionary* dict;
@end

@implementation Foo
- (NSString *)description {
    // super.description for the <{classname} pointer> output
    return [NSString stringWithFormat:@"%@ %@", super.description, self.dict];
}
@end

以及人为的用法

Foo* f0 = [[Foo alloc] init];
f0.dict = @{ @"value": @0, @"next": NSNull.null };
Foo* f1 = [[Foo alloc] init];
f1.dict = @{ @"value": @1, @"next": f0 };
Foo* f2 = [[Foo alloc] init];
f2.dict = @{ @"value": @2, @"next": f1 };

我们得到了很好的输出f0

(lldb) po f0
<Foo: 0x8cbc410> {
    next = "<null>";
    value = 0;
}

容许输出f1

(lldb) po f1
<Foo: 0x8cbc480> {
    next = "<Foo: 0x8cbc410> {\n    next = \"<null>\";\n    value = 0;\n}";
    value = 1;
}

和可怕的输出f2

(lldb) po f2
<Foo: 0x8cbc4b0> {
    next = "<Foo: 0x8cbc480> {\n    next = \"<Foo: 0x8cbc410> {\\n    next = \\\"<null>\\\";\\n    value = 0;\\n}\";\n    value = 1;\n}";
    value = 2;
}

在调试现实世界的对象层次结构时,这很难快速解析。我假设自从转储类似的嵌套 NSDictionary 以来我还缺少一些其他技巧

NSDictionary* d0 = @{ @"value": @0, @"next": NSNull.null };
NSDictionary* d1 = @{ @"value": @1, @"next": d0 };
NSDictionary* d2 = @{ @"value": @2, @"next": d1 };

保持缩进并避免逃离地狱

(lldb) po d2
{
    next =     {
        next =         {
            next = "<null>";
            value = 0;
        };
        value = 1;
    };
    value = 2;
}

UPDATE

切换到-debugDescription并简单地转发到字典

@implementation Foo
- (NSString *)debugDescription {
    return self.dict.debugDescription;
}
@end

丢失递归输出

(lldb) po f2
{
    next = "<Foo: 0x8b70e20>";
    value = 2;
}

内部NSDictionary必须依靠-description我在这个例子中没有实现,只是-debugDescription。切换到类似下面的内容

@implementation Foo
- (NSString *)description {
    return self.dict.description;
}
- (NSString *)debugDescription {
    return self.dict.debugDescription;
}
@end

也会产生同样糟糕的输出

(lldb) po f2
{
    next = "{\n    next = \"{\\n    next = \\\"<null>\\\";\\n    value = 0;\\n}\";\n    value = 1;\n}";
    value = 2;
}

TL;DR;

Use NSContainers-PrettyPrint http://openradar.appspot.com/10765424并仔细地read https://github.com/NSError/NSContainers-PrettyPrint/blob/master/String-Tools.md the docs https://github.com/NSError/NSContainers-PrettyPrint/blob/master/Best-Practices.md.

长答案

经过更多搜索后我发现descriptionWithLocale:indent: https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSDictionary_Class/Reference/Reference.html#//apple_ref/occ/instm/NSDictionary/descriptionWithLocale:indent:方法。如文档所述,我应该能够在我自己的类中实现这一点,以实现所需的漂亮打印格式。然而,经过一些失败的尝试后,我发现了一个类似的问题 https://stackoverflow.com/questions/7521683/nsdictionary-description-formatting-problem-treats-structure-like-char-data。事实证明descriptionWithLocale:indent:仅当出于“安全考虑”而对 Foundation 容器类进行子类化时才有效。

对这种方法不满意,我继续挖掘并发现了这个radar http://openradar.appspot.com/10765424也是一个解决方案NSContainers-PrettyPrint https://github.com/NSError/NSContainers-PrettyPrint。经过一番尝试和错误后,我的工作进展顺利。 (它不在 CocoaPods 上,因此您必须手动添加)。

添加 NSContainers-PrettyPrint 后,您可能会想要JRSwizzle https://github.com/rentzsch/jrswizzle也。然后定义DEBUGPRINT_ALL and DEBUGPRINT_SWIZZLE在您的 DEBUG 目标预处理器宏中。最后,您可以实施您的descriptionWithLocale:indent:方面的方法fs_* 助手 https://github.com/NSError/NSContainers-PrettyPrint/blob/master/String-Tools.md and 最佳实践 https://github.com/NSError/NSContainers-PrettyPrint/blob/master/Best-Practices.md.

使用相同的Foo以我的问题为例

@implementation Foo
- (NSString*)description
{
    return [NSString stringWithFormat:@"%@ %@", super.description, self.dict.description];
}

- (NSString *)descriptionWithLocale:(id)locale indent:(NSUInteger)level
{
    NSString * indent = [NSString fs_stringByFillingWithCharacter:' ' repeated:fspp_spacesPerIndent*level];
    NSMutableString * str = [[NSMutableString alloc] init];
    [str fs_appendObjectStartWithIndentString:indent caller:self];
    [str appendString:[self.dict descriptionWithLocale:locale indent:level+1]];
    [str fs_appendObjectEnd];
    return str;
}
@end

给出相同的情况下会产生以下输出f0, f1 and f2实例

(lldb) po f0
<Foo: 0x8a385c0> {
    value = 0;
    next = <null>;
}
(lldb) po f1
<Foo: 0x8a38630> {
    value = 1;
    next = <Foo:0x8a385c0        {
            value = 0;
            next = <null>;
        }>;
}
(lldb) po f2
<Foo: 0x8a38660> {
    value = 2;
    next = <Foo:0x8a38630        {
            value = 1;
            next = <Foo:0x8a385c0                {
                    value = 0;
                    next = <null>;
                }>;
        }>;
}

以上descriptionWithLocale:indent:可以使用一些调整来减少过多的空白,但它仍然胜过其他选择。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

调试器(或日志)中类似 NSDictionary 的漂亮打印 的相关文章

  • 启动深色或浅色模式的图像

    如何为深色模式和浅色模式选 择一组不同的启动图像 我有一个 LaunchImages 集 当应用程序启动时 会显示一个图像 对于浅色模式 这似乎不错 但是如果我尝试在设置为深色模式 iOS 13 的设备上打开我的应用程序 则该图像看起来很糟
  • 重叠的装载机圆

    我试图重现苹果为应用程序 活动 制作的重叠圆圈 见下图 如果您使用标准贝塞尔路径 起始 结束位置将仅在 0 到 2PI 之间产生影响 例如 如果您尝试填充 4PI 即使使用一些阴影 则无法模拟重叠加载 如何制作类似于苹果解决方案的东西来创建
  • html 空格引起的非常奇怪的错误

    我在 Firefox 中遇到了一个非常奇怪的错误 我在外部文件中有一个 javascript 函数 可以在常规复杂性网站上完美运行 然而 我一直在整理一些演示示例并遇到一些奇怪的事情 html 格式如下 在编辑器中 div p Q Wher
  • 将自定义图像设置为 UIBarButtonItem 但它不显示任何图像

    我想将自定义图像设置为 UIBarButtonItem 但它只显示周围的矩形框并且不显示实际图像 func setupBrowserToolbar let browser UIToolbar frame CGRect x 0 y 20 wi
  • 添加/删除带有动画的 UITableViewCell?

    我知道这听起来像是一个愚蠢的问题 但我到处都看过 我怎样才能做到这一点 我知道如何使用 swype to delete 方法来执行此操作 但是我如何在该函数之外执行此操作 请发布一些代码示例 Thanks Coulton self tabl
  • 为 iOS 应用程序加载基于 SVG 的图像资源

    我从 thenounproject 购买了一个图标作为 SVG 图像 然后我使用一个名为的 macOS 程序Gapplin http gapplin wolfrosch com 将此 SVG 导出为 PNG 图像 它显示为 100x100
  • 对成员“buildBlock()”的引用不明确

    我一直在尝试使用 Swift UI 为 iOS 13 制作一个应用程序 但我不断收到这个奇怪的错误 对成员 buildBlock 的引用不明确 无论我做什么 错误都不会消失 我尝试一次对代码段进行注释 以查看哪一部分可能导致了问题 但唯一有
  • 从 Mac 命令行访问 iOS 应用程序目录(沙箱)

    我需要使用 Mac 或 Linux 上的命令行 非 GUI 访问 iOS 设备上安装的应用程序的沙箱目录 这有助于开发和测试自动化 将 json 文件放入沙箱中可以让我设置参数 例如额外的调试消息和更小的刷新间隔 像 iFunBox 这样的
  • 查找已用应用程序名称的捆绑包/开发人员

    我正在尝试将应用程序上传到应用程序商店并收到以下错误 很容易理解 The App Name you have entered has already been used 该应用程序不在 iTunes 上 有什么方法可以找出谁拥有该应用程序或
  • UITableView 滑动删除 iOS 上的手势冲突

    我的手势识别器有问题 我的目标是在表视图中实现使用滑动删除 但我认为其他手势是相互冲突的 我正在使用这个库romonthego REFrostedViewController https github com romaonthego REF
  • 在文本视图滚动之前无法看到 UITextView 中的文本

    我的应用程序中有一堆文本视图 由于某种原因 无论我以编程方式 来自互联网 还是通过界面生成器 硬编码 设置 UITextView 文本 无论我做什么 当我在测试时转到该文本视图时它都是空白的 但当我滚动它的那一刻 所有文本就突然出现了 只是
  • 如何从 AFNetworking 和 AFJSONRequestOperation 获取可变字典?

    我将 JSONKit 与 AFNetworking 的 AFHTTPClient 带有 AFJSONRequestOperation 一起使用 我似乎无法弄清楚如何触发使用 JSONKit 的 mutableObjectFrom 方法 而不
  • 从什么时候起 Xcode 不再需要前向方法声明,为什么?

    我注意到 Xcode 或更准确地说是 Apple LLVM 编译器 不再需要前向方法声明 换句话说 构建以下代码时不会发出警告 implementation Foo void foo self bar void bar end 这曾经发出警
  • 在 Xcode4 中使用 Boost

    有人设置 C Xcode4 项目来使用 Boost 吗 对于一个简单的 C 控制台应用程序 我需要在 Xcode 中设置哪些设置 Thanks 用这个来管理它 和这个
  • 在视图之间传递核心数据实体变量

    我无法理解如何在视图之间使用核心数据实体变量 为了更好地理解我的问题是什么 我的代码如下 View A 基本上 您必须将完整预算实体或相关预算实体的 ID 从视图 A 传递到视图 B 由于不知道您的应用程序的视图层次结构和逻辑 我假设您选择
  • 高效创建 x 层深度的嵌套 for 循环

    这可能是一件简单的事情 但我需要创建一个循环结构 使其循环 y x 次以创建 x 和 y 的所有可能组合 例如 如果有 4 个 x 每个 x 有 2 个 y 我想做这样的事情 for int a 0 a lt y a for int b 0
  • ios - 在哪里放置 s.static_framework = true

    我在 CocoaPods 中的级别为 0 当我使用pod install有一个错误说 The Pods App target has transitive dependencies that include static framework
  • 如何将相机中的图像保存到 iPhone 图库中的特定文件夹?

    嘿 我是 iPhone 新手 最近我一直在尝试制作一个应用程序 基本上 我想要做的是 如果用户将从相机捕获任何图像 那么它应该保存在设备库中 我知道如何将照片保存在图库中 它对我有用 但我无法将所有捕获的图像保存到设备图库中的特定文件夹 例
  • iOS 电池监控 Swift

    我已将监控设置为启用 但模拟器和设备中的电池电量仍然为 1 UIDevice currentDevice batteryMonitoringEnabled true var level UIDevice currentDevice batt
  • 设置/覆盖 UICollectionView 中单元格之间的填充

    我有一个 UICollectionView 但在获取单元格之间的填充时遇到了问题 理论上 我应该能够将屏幕除以 4 并且我可以获得包含 4 个图像的单元格大小 完美地占据屏幕宽度 但是 它选择不这样做 相反 它会创建 3 个具有巨大填充的图

随机推荐

  • Angular 通用 html lang 标签

    在 Angular Universal 中 我有一个 index html 文件 顶部有 我想根据我所在的页面更改此设置 maldonadoattorney com es jailreleases 将是 maldonadoattorney
  • Django - 使用模板标签和“with”?

    我有一个自定义模板标签 def uploads for user user uploads Uploads objects filter uploaded by user problem upload False num uploads u
  • 基于支持向量的数据重采样器

    我正在努力实现一个数据重采样器以基于support vectors 这个想法是为了适应SVM分类器 得到support vector类的点 然后通过仅选择每个类的支持向量点附近的数据点来平衡数据 以使类具有相同数量的示例 忽略所有其他 远离
  • Google Plus API 错误gapi.loaded_0

    我尝试将 requireJS 与 Google plus API 一起使用 但是当我单击登录按钮时出现错误 这是错误和屏幕截图 GET https apis google com scs apps static js k oz gapi e
  • 如何在pytorch中使用LSTM进行分类?

    我的代码如下 class Mymodel nn Module def init self input size hidden size output size num layers batch size super Discriminato
  • 在非活动类中显示进度对话框

    我正在尝试在非活动类中显示对话框 基本上 我在我的应用程序中检测到一个对象 我想显示一个对话框 然后切换活动 我在 logcat 中收到 java lang RuntimeException 无法在未调用 Looper prepare 的线
  • 链接方法时如何返回 false

    我有一个使用方法链的验证类 我希望能够进行单次检查TRUE FALSE像这样 if obj gt checkSomething 但也有像这样的链方法 if obj gt checkSomething gt checkSomethingEls
  • 将代码转换为 R 中的函数

    我有一系列的步骤 我想将它们转换为函数 因此我只需通过调用它们即可将其应用于数据框 下面是带有一些注释的代码 library textreadr library pdftools library tidyverse library tidy
  • 函数上的模板模板参数

    这是 C 模板中的有效模板构造吗 template lt template
  • 在Qt中鼠标指针下选择Word

    当我在 QTextBrowser 中右键单击时 我需要突出显示并获取鼠标指针下的单词 我已经实施了显示上下文菜单函数为QText浏览器对于鼠标右键单击的事情 但是我无法突出显示鼠标指针下的单词并提取它 我在网上找到了如下解决方案 QText
  • 为什么这个 getchar() 循环在输入一个字符后停止?

    include
  • swig 没有名为 _example 的模块

    我无法在 Windows 上重现基本的 SWIG 示例 我的错误已在 SWIG 文档中说明 我确信我已执行他们提到的 2 个修复 对于这个错误 gt gt gt import example Traceback most recent ca
  • 编辑 php.ini 文件

    我想增加内存限制 最大输入时间 最大执行时间 in WAMP server 有 3 个php ini files 1 C wamp bin apache Apache2 4 4 bin php ini br 2 C wamp bin php
  • AngularJS:ng-bind-html 不适用于按钮标签

    我在 div ng bind html 中动态打印输入类型按钮时遇到问题 HTML 模板
  • 为什么当我更新实体框架模型时 Visual Studio 会删除我的类

    当我更新 EF 模型 版本 5 时 我遇到了一个奇怪的问题 它删除属于该模型的所有类 我的情况是这样的 我更改了两个表的键列 这两个表引用了我的主表 更新模型并未对 edmx 进行这些更改 因此我删除了这三个表 主表和两个查找表 保存了 e
  • Firebase android 无法在测试设备之外工作

    我有这个新应用程序 并添加了 Firebase Firestore 和 Cloud Firestore 用户可以使用邮箱和密码进行注册 并登录成功 然后用户可以在我的个人资料中输入生日并更新信息 问题是这样的 在模拟器中工作正常 在测试设备
  • Oracle:年份必须介于 -4713 和 +9999 之间,并且不能为 0

    我有一个像这样的 Oracle 表 EMPNO HIREDATE INDEX NUM 1 2012 11 13 1 2 2 1 3 2012 11 17 1 4 2012 11 21 1 5 2012 11 24 1 6 2013 11 2
  • Symfony 2.4 从控制器执行命令

    我想从我的控制器执行命令 fos elastica populate 我尝试了该代码 但它不起作用 我得到错误 1 var dump 显示 command fos elastica populate app new Application
  • 将 ASP.NET 菜单控件绑定到 XML

    我正在尝试将我自己的 xml 文件 出于某些特定目的 我不想使用站点地图 绑定到 ASP NET 控件 我有这段代码 在我找到的一些文章的帮助下 应该将 ASP NET 菜单控件绑定到 xml 文件 但事实并非如此 我错过了什么吗 XmlD
  • 调试器(或日志)中类似 NSDictionary 的漂亮打印

    这已经困扰我一段时间了 如何抵消在调试器中转储对象时发生的丑陋转义po foo 或通过NSLog 我尝试了多种方法来实施 description or debugDescription无济于事 鉴于这个简单的类 interface Foo