Til*_*ill 32 iphone trace nsnotifications
为了更好地理解"引擎盖下"发生的事情,我希望对我的应用程序中发生的任何通知进行完整的跟踪.
像我一样天真,我尝试的第一件事就是这样注册:
我的应用程序的某个地方:
{
[...]
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(traceNotifications:) name:nil object:nil];
[...]
}
- (void)traceNotifications:(NSNotification *)notification
{
NSLog(@"received notification %@", [notification name]);
}
Run Code Online (Sandbox Code Playgroud)
我实际上通过这种方式获得了许多通知.但在某些时候,应用程序确实崩溃了.堆栈跟踪显示它在realizeClass中与EXC_BAD_ACCESS崩溃,根据我的经验,它确实表明在释放后调用了某些东西.然而,我的观察对象仍然存在,它的解除分配器尚未被调用.
我试过的下一件事是设置一个断点-[NSNotificationCenter postNotification:],然后po {NSNotification *}($ebp+16)每当我的断点被困时在gdb-console内部运行.这确实揭示了一些通知,但不是我期望/希望的所有通知.例如,我的应用程序确实正确处理了方向更改,但在重新定向设备时(在模拟器中)我没有看到任何通知被捕获.
我错过了什么?有没有办法(例如工具)可靠地观察NSNotificationCenter?
谢谢你的任何提示.
Til*_*ill 58
我开始工作的唯一解决方案是使用断点.
我在__CFXNotificationPost_old(CoreFoundation)添加了一个断点,并将其与调试器命令捆绑在一起po {NSNotification *}($ebp+12).所有这些在Xcode GUI中都很好用:
每当发布NSNotification时,应用程序将停止执行并在gdb-console中显示它.
我确实试图在gdb中创建一个跟踪点但是失败了,因为Xcode gdb中的跟踪点操作似乎有些错误 - 或者我可能只是太过stoopid而无法使用它们.
我也试图创建一个自定义的仪器Dtrace脚本,但失败了,因为我的Dtrace空手道不够强大.
如果您设法让后面的任何一个选项起作用,请继续将它们作为替代答案发布 - 我将进行投票并将其标记为受欢迎的选项.
UPDATE
在这个问题之后,我找到了在CoreFoundation级别捕获所有通知的正确方法.
这是如何做到的:
void MyCallBack (CFNotificationCenterRef center,
void *observer,
CFStringRef name,
const void *object,
CFDictionaryRef userInfo)
{
NSLog(@"name: %@", name);
NSLog(@"userinfo: %@", userInfo);
}
CFNotificationCenterAddObserver(CFNotificationCenterGetLocalCenter(),
NULL,
MyCallBack,
NULL,
NULL,
CFNotificationSuspensionBehaviorDeliverImmediately);
Run Code Online (Sandbox Code Playgroud)
我实际上感到有点惭愧,我以前没有仔细看过CoreFoundation的界面.
Ben*_*tow 21
嘿直到 - 我经常使用通知,我也有一些严重的问题调试它们.我最近发布了一个名为Spark Inspector(http://sparkinspector.com/)的应用程序,它使这个过程变得更容易.您向应用程序添加了一个框架,它会调动NSNotificationCenter,以便您可以在我们的应用程序中查看发送和接收的所有通知的表格,其中包含发送它们的堆栈跟踪以及观察它们的所有方法的列表.我知道它已经晚了三年,但它可能会有所帮助!

Mar*_*sel 15
我知道发布的问题已经过时了,但我想我会回复几行代码.
您可以通过此块查看应用程序运行时发布的所有通知:
[[NSNotificationCenter defaultCenter] addObserverForName:nil
object:nil
queue:nil
usingBlock:^(NSNotification *notification) {
NSLog(@"%@", notification.name);
}];
Run Code Online (Sandbox Code Playgroud)
将其添加到适当视图控制器的viewWillAppear方法.(当然,在准备应用程序以进行任何类型的分发时,您应该从代码中删除它.)
另外,请务必添加以下内容:
[[NSNotificationCenter defaultCenter] removeObserver:self];
Run Code Online (Sandbox Code Playgroud)
到您选择的视图控制器的相应viewWillDisappear方法.
更新:相同的答案,但在Swift中:
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
NSNotificationCenter.defaultCenter().addObserverForName(nil,
object: nil,
queue: nil) {
note in
print(note.name + "\r\n")
}
}
override func viewWillDisappear(animated: Bool) {
NSNotificationCenter.defaultCenter().removeObserver(self)
super.viewWillDisappear(animated)
}
Run Code Online (Sandbox Code Playgroud)
出于调试目的,我发现断点实际上比向项目中添加代码要好。但是,@ Till的解决方案似乎对我不起作用。我在网上找到了另一个解决方案,并对其进行了一些调整。
符号断点
- 符号:
-[NSNotificationCenter postNotificationName:object:userInfo:]- 条件:
((NSRange)[$arg3 rangeOfString:@"^(_|NS|UI)" options:1024]).length == 0- 行动:调试器命令
po $arg3- 评估动作后自动继续
笔记:
_,NS或UI从被显示。1024指向NSRegularExpressionSearch,该断点似乎不可用。.length == 0而不是,.location == NSNotFound因为NSNotFound似乎计算出的值(-1或(NSUInteger)18446744073709551615)不同于此断点(9223372036854775807)中返回的值。| 归档时间: |
|
| 查看次数: |
10200 次 |
| 最近记录: |