如何在Xcode lldb swift repl中与对象进行交互式玩耍?

5
假设我有一个小程序,它涉及从数据库中选择文档:
let errorDatabase
= NSError(domain: "dk.myproject.couchbase", code: 0, userInfo: nil)

let rev = database.existingDocumentWithID("_design/" + designDocName)
// in xcode I set a break point here
assert(rev != nil)
if rev == nil {
    promise.failure(errorDatabase)
}

然后我插入一个断点,运行程序后可以进行以下操作:

(lldb) po rev
0x00007fad21df61c0
 {
  ObjectiveC.NSObject = {...}
}
(lldb) print rev.properties["views"]
(AnyObject?) $R29 = Some {
...

接下来让我们进入repl并与rev对象互动:

(lldb) repl
6> rev
repl.swift:6:1: error: use of unresolved identifier 'rev'
rev
^

我可能对 Swift REPL 的期望有误 - 我期望它能像 Python、Node.js 或 Scala REPL 一样,可以玩弄对象等。

有什么提示吗?

2个回答

11

第一次在LLDB中输入repl时,我也希望能够做到同样的事情,但很快就发现不幸的是你做不到。

LLDB内部的repl实际上是在顶级注入模块中运行的。因此,你可以在此处的repl中定义顶级对象和函数,然后在“正常”的lldb中可见:

(lldb) repl
1> func pt() -> CGPoint {
2. return CGPointZero
3. }
4> :
(lldb) po pt()
(0.0, 0.0)

...但反之不成立:您不能在repl中查看您暂停时点的局部变量,因为它们显然不在顶层作用域内。

但需要注意的是,您可以在expr表达式中执行赋值操作。因此,您可以通过输入expr加上一个赋值语句来更改局部变量或现有对象的属性等,并且这确实发生在您暂停的上下文中。

例如,假设我正在创建一个pan手势识别器,我在这一行设置了断点:

p.edges = UIRectEdge.Right

现在:

(lldb) th step-over
(lldb) expr p.edges = UIRectEdge.Left
(lldb) continue

现在应用程序正在运行,但手势识别器会在从左侧滑动而不是右侧滑动时发挥作用。


好的,这也很有用~虽然我本来希望是另一种方式 :) - pellekrogholt
我知道,我也很失望。 :( 我最初做了与你相同的梦想。但是它没有奏效,所以我观看了 WWDC 2014 视频,他们非常清楚关于顶级模块注入的事情。 - matt
请注意,您可以从简单的 expr 中获得一些优势,它确实在上下文中发挥作用。我会把这加入到我的答案中。 - matt
expr 中添加了一个实际的赋值示例。 - matt
现在我们有了Xcode10,当前状态如何?有人知道现在在Xcode10中是否可以在repl中“看到”lldb中的对象吗?经过一番搜索,似乎仍然无法在swift repl中看到lldb对象,但我希望有人能证明我是错的? - Andrej

2
请注意,我在这个问题中描述了“表达式”和“repl”之间的目的和区别:
Xcode 6.1 'Swift REPL内置于Xcode调试器中,可以检查和操作您运行的应用程序'不起作用
也许这会帮助您理解您看到的相似之处和差异以及它们背后的意图。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接