如何在XCode 4中特定类的特定属性的"objectAtIndex:"方法上设置断点?

Kla*_*nis 10 xcode breakpoints objective-c xcode4

我想在特定类中的特定属性的"objectAtIndex:"方法上设置符号断点.

请参阅以下代码:

@interface Foo
...
@property (strong,nonatomic) NSMutableArray *fooArray;
...
@end
Run Code Online (Sandbox Code Playgroud)

我尝试过以下事情:

  • -[[Foo fooArray] objectAtIndex:]
  • -[Foo::fooArray objectAtIndex:]
  • -[Foo::fooArray objectAtIndex]
  • Foo::fooArray::objectAtIndex:
  • Foo::fooArray::objectAtIndex
  • Foo::fooArray::objectAtIndex()

这些解决方案都不起作用.

有什么想法可以做到这一点吗?

Pet*_*sey 5

不幸的是,虽然这很有用,但由于多种原因,它无法工作.

第一个涉及如何指定方法.用于标识断点中的方法的方法签名有三个部分:

-¹[NSDictionary² objectForKey:³]
+¹[NSString² stringWithContentsOfURL:encoding:error:³]
Run Code Online (Sandbox Code Playgroud)
  1. 这是实例方法( - )还是类方法(+)?
  2. 哪个类实现了这个方法?
  3. 这种方法的选择器是什么?

所以你的第一个问题是你为#2写的不是一个类.

你所拥有的是一个类,以某种方式跟随属性名称.这不起作用,因为调试器无法知道它是否是纯访问器 - 它无法确定您或实现该属性的任何人没有编写执行其他操作的自定义访问器.这意味着调试器没有良好,可靠的方法来获取该值,或者知道该值何时发生更改,而不会产生副作用.

此外,类在方法签名中的作用是识别哪个类提供了您正在设置断点的实现.一旦你开始尝试引用一个包含对象的属性,那就会出现在窗口中,因为调试器需要一个类,并且必须从对象中获取它 - 并且看一下上一段中的一些困难.知道哪个对象一直都是.

(公平地说,调试器确实可以观察实例变量-IIRC的值,两个调试器都可以在观察点中执行此操作,尽管上一次尝试时,观察点的可靠性是不稳定的.如果是调试器可以将该属性转换为其支持ivar,如果它有一个,并注意,对于大多数属性来说,这将是一个不错的90%解决方案,它没有富有想象力的存储实现和自定义访问器的支持.但调试器不能做今天这个.)

第二个原因是NSArray是一个类集群.

您可能已经知道了第一部分(我怀疑这就是您尝试通过另一个属性指定单个对象的原因):

NSArray和NSMutableArray都是抽象类,这反过来意味着没有人实现作为数组的业务; 每一个都实现了一堆方便的方法,同时留下一组未实现的核心方法,供子类实现.

因此,在创建NSArray时,不要创建NSArray.您获取的对象将是NSArray的某个私有子类的实例,它自己实现了它如何管理有序的对象列表的所有细节.

所以你可以设置一个断点,比如说,-[NSArray objectAtIndex:]但它永远不会被击中,因为没有使用NSArray的-it实现objectAtIndex:就没有意义使用该实现,因为该实现引发了一个异常(旨在捕获忘记实现的子类)它).

打破你的问题的部分是:

虽然NSArray的各种非必要方法的实现最终是根据核心方法定义的,例如objectAtIndex:,这并不意味着子类必然会使用这些实现.子类很可能有自己的实现不使用objectAtIndex:,如果objectAtIndex:不是最有效的方式来做他们做的事情(例如,如果数组由链表而不是C数组支持).

所以,总结这个长期答案:

  • 调试器无法可靠地监视属性的值.
  • 因此,当调用作为该属性值的对象类中的方法时,调试器不可能中断,因为设置断点的正确方法可能随时更改,并且调试器不能知道什么时候发生.
  • 即使您可以破坏objectAtIndex:属性标识的某个对象,该数组也可能永远不会使用objectAtIndex:,在这种情况下,您的断点永远不会被击中.

你可能应该通过打破问题来提出另外一个关于你想要做什么的问题objectAtIndex:.我假设您正在尝试调查您应用中的错误; 那个bug可能是另一个有趣的问题.


n-b*_*n-b 5

经过一番挖掘,我找到了解决这个问题的方法.那有点难看.

它涉及在由第一个断点触发的命令中动态创建条件断点.

首先,每当你的fooArray准备好时休息.我决定使用fooArray存取器,但可以提前完成:

breakpoint set --name "-[Foo fooArray]"

然后,当您objectAtIndex:在此特定数组对象上调用时,您想要的是中断.首先让我们把它的指针放在一个变量中:

expr id $watch = self->_fooArray

然后在条件中使用此变量创建一个新断点:

breakpoint set --name "-[__NSArrayI objectAtIndex:]" --condition "$rdi == $watch"

  • $rdi包含self,至少在x86_64.$r0在ARM上使用.(请参阅Clark Cox 关于该主题精彩帖子.)
  • -[NSArray objectAtIndex:]永远不会被称为.正如Peter所说,NSArray是一个类集群,你的数组实际上是一个__NSArrayI.

或者,在Xcode中:

Xcode动态断点

(别忘了勾选"继续"框.)

它不是很漂亮,但似乎有效!


tro*_*foe 1

我不在 Mac 旁,所以我不能自己尝试这个,但是怎么样:

breakpoint set -n "-[[Foo fooArray] objectAtIndex:]" 
Run Code Online (Sandbox Code Playgroud)