Xcode + LLDB:尝试使用 'expression' 更改变量值

Xcode + LLDB: trying to change variable value using 'expression'

我正在努力提高我的调试技能,所以开始阅读 here。我有以下代码:

var label = "tom"
self.label.text = label
print(label)

我在每一行中都有一个断点,我在每一行中输入

expression label = "jones"
po label

因此,当我键入 po label 时,我得到了预期的结果,即 jones,但标签和控制台(来自 print(label))中显示的文本是 tom.

我链接的教程指出更改应该对整个 运行 程序生效。这是假的,还是我做错了什么?

我正在使用 Xcode 版本 8.2.1 (8C1002) 和 iPhone 7 Plus 模拟器。

谢谢!

我不确定这是否有帮助,但实际情况比您想象的要复杂一些。

Swift 字符串实际上是结构,因此如果您在分配给 self.text.label 之前停在行上并为 label var 分配一个新值,您实际上是在改变结构的内容,这应该意味着当您从该结构分配给 self.text.label 时,它确实应该获取新值...

不起作用的原因是 swift 编译器很聪明地拆箱这些结构,因此它不会在可能的情况下进行不必要的取消引用。即使在 -Onone.

也会发生这种情况

因此,例如,在您的示例中,swift 编译代码已经对字符串进行拆箱并发出直接引用内容的代码。更改实际的字符串内容不会更改对赋值代码中已拆箱内容的引用,因此您的更改不会生效。

你可以看到这个IRL:如果你让编译器不知道字符串的内容是什么,它就不能做这个拆箱,然后你会看到你的调试器更改生效。

使用此示例代码:

class HasLabel
{
  var label : String = "Default Value"
}

func 
main ()
{
  var myLabel = HasLabel()
  var string = "set in code"

  string.removeSubrange(string.startIndex..<string.endIndex)
  string.append("Different string in code")
  myLabel.label = string  // Set a breakpoint here
  print ("Did it change? string: \"\(string)\" Label: \"\(myLabel.label)\"")
}

main()

在调试器中,我看到:

(lldb) br s -p "Set a breakpoint here"
Breakpoint 1: where = tryme`tryme.main () -> () + 499 at tryme.swift:14, address = 0x0000000100001e93
(lldb) run
Process 8323 launched: '/private/tmp/tryme' (x86_64)
Process 8323 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
    frame #0: 0x0000000100001e93 tryme`tryme.main () -> () at tryme.swift:14
   11   
   12     string.removeSubrange(string.startIndex..<string.endIndex)
   13     string.append("Different string in code")
-> 14     myLabel.label = string  // Set a breakpoint here
          ^
   15     print ("Did it change? string: \"\(string)\" Label: \"\(myLabel.label)\"")
   16   }
   17   
(lldb) expr string = "Set in debugger"
(lldb) c
Process 8323 resuming
Did it change? string: "Set in debugger" Label: "Set in debugger"
Process 8323 exited with status = 0 (0x00000000) 

您可以看到实际发生的调试器更改。但是如果你注释掉string.removeSubrangestring.append,那么改变就不再需要了。