是否可以在 Swift 属性上设置观察点?
Is it possible to set watchpoints on Swift properties?
在 Objective-C 中,有时我会在 LLDB 中设置观察点,让我知道实例变量何时发生变化。我也可以使用 Swift 属性来做到这一点吗?
现在,我能做到这一点的唯一方法是:
- 向 属性 添加一个 didSet 处理程序并在其中设置一个断点(但这需要停止程序并重新编译,这会破坏目的)
- 在
[setPropertyName:]
上添加符号断点,但这仅在 class 恰好支持 Objective-C 桥接 时有效
我还有其他选择吗?
答案比我想象的要简单得多。最简单的方法是在 属性 声明上简单地添加一个断点。只要读取或写入 属性,调试器就会中断。
如果像我一样,您只想在 属性 更改时中断并忽略提取,请在 属性 声明上设置断点,然后进入 LLDB 控制台并键入 "br list" 查看所有断点的列表:
(lldb) br list
Current breakpoints:
1: file = '/Users/testuser/Desktop/TestFoo/Test.swift', line = 12, locations = 3, resolved = 3, hit count = 1
1.1: where = TestFoo`TestFoo.Test.x.getter : Swift.Int + 12 at Test.swift:12, address = 0x00000001084cfefc, resolved, hit count = 1
1.2: where = TestFoo`TestFoo.Test.x.setter : Swift.Int + 16 at Test.swift:12, address = 0x00000001084cff80, resolved, hit count = 0
1.3: where = TestFoo`TestFoo.Test.x.materializeForSet : Swift.Int + 16 at Test.swift:12, address = 0x00000001084d00f0, resolved, hit count = 0
如您所见,有一个主断点“1”和三个子断点。禁用 getter:
的子断点
(lldb) br disable 1.1
1 breakpoints disabled.
一切就绪。只有当 属性 被修改时,调试器才会中断。
On XCode (8.2 Swift 3.0) 通常在 swift 属性 然后 运行 您的应用程序上设置断点。在应用程序 运行 转到断点面板后,您可以将断点扩展为多个断点:
默认情况下全部选中,然后您可以禁用不需要的那些。
注意:我发现当您第一次添加断点时它不会扩展,直到您 运行 应用程序。
您可以尝试的另一种方法是使用 lldb 添加它们。首先在 class 实例中的某处添加断点,例如 viewDidLoad 分机。 p self 并记下您的实例的内存地址。
然后像这样添加断点,其中 0x0f0f0f0f0f0f 是您对象的内存地址。
break set -F '-[MyClass setMyProperty:]' -c '$rdi == 0x0f0f0f0f0f0f'
在 Objective-C 中,有时我会在 LLDB 中设置观察点,让我知道实例变量何时发生变化。我也可以使用 Swift 属性来做到这一点吗?
现在,我能做到这一点的唯一方法是:
- 向 属性 添加一个 didSet 处理程序并在其中设置一个断点(但这需要停止程序并重新编译,这会破坏目的)
- 在
[setPropertyName:]
上添加符号断点,但这仅在 class 恰好支持 Objective-C 桥接 时有效
我还有其他选择吗?
答案比我想象的要简单得多。最简单的方法是在 属性 声明上简单地添加一个断点。只要读取或写入 属性,调试器就会中断。
如果像我一样,您只想在 属性 更改时中断并忽略提取,请在 属性 声明上设置断点,然后进入 LLDB 控制台并键入 "br list" 查看所有断点的列表:
(lldb) br list
Current breakpoints:
1: file = '/Users/testuser/Desktop/TestFoo/Test.swift', line = 12, locations = 3, resolved = 3, hit count = 1
1.1: where = TestFoo`TestFoo.Test.x.getter : Swift.Int + 12 at Test.swift:12, address = 0x00000001084cfefc, resolved, hit count = 1
1.2: where = TestFoo`TestFoo.Test.x.setter : Swift.Int + 16 at Test.swift:12, address = 0x00000001084cff80, resolved, hit count = 0
1.3: where = TestFoo`TestFoo.Test.x.materializeForSet : Swift.Int + 16 at Test.swift:12, address = 0x00000001084d00f0, resolved, hit count = 0
如您所见,有一个主断点“1”和三个子断点。禁用 getter:
的子断点(lldb) br disable 1.1
1 breakpoints disabled.
一切就绪。只有当 属性 被修改时,调试器才会中断。
On XCode (8.2 Swift 3.0) 通常在 swift 属性 然后 运行 您的应用程序上设置断点。在应用程序 运行 转到断点面板后,您可以将断点扩展为多个断点:
默认情况下全部选中,然后您可以禁用不需要的那些。 注意:我发现当您第一次添加断点时它不会扩展,直到您 运行 应用程序。
您可以尝试的另一种方法是使用 lldb 添加它们。首先在 class 实例中的某处添加断点,例如 viewDidLoad 分机。 p self 并记下您的实例的内存地址。
然后像这样添加断点,其中 0x0f0f0f0f0f0f 是您对象的内存地址。
break set -F '-[MyClass setMyProperty:]' -c '$rdi == 0x0f0f0f0f0f0f'