Objective c NSDrawer委托指向解除分配的对象?

Objective c NSDrawer委托指向解除分配的对象?,objective-c,cocoa,delegates,Objective C,Cocoa,Delegates,一个用户发送了一个崩溃报告,其中包含下面列出的堆栈跟踪(我自己无法复制崩溃,但该用户报告的每一个其他崩溃都是一个有效的错误,即使我无法复制效果)。该应用程序是一个参考计数的Objective-C/Cocoa应用程序 如果我的解释正确,则崩溃是由于试图向解除分配的对象发送drawerdipopen:消息引起的。唯一应该接收drawerDidOpen:的对象是出票人的委托对象(没有任何对象注册以接收出票人通知),出票人的委托对象通过XIB/NIB文件实例化,连接到出票人的委托出口,不在其他任何地方引

一个用户发送了一个崩溃报告,其中包含下面列出的堆栈跟踪(我自己无法复制崩溃,但该用户报告的每一个其他崩溃都是一个有效的错误,即使我无法复制效果)。该应用程序是一个参考计数的Objective-C/Cocoa应用程序

如果我的解释正确,则崩溃是由于试图向解除分配的对象发送
drawerdipopen:
消息引起的。唯一应该接收
drawerDidOpen:
的对象是出票人的委托对象(没有任何对象注册以接收出票人通知),出票人的委托对象通过XIB/NIB文件实例化,连接到出票人的委托出口,不在其他任何地方引用

鉴于此,我如何防止代理在抽屉通知之前被解除锁定?或者,或者,我误解了可能导致崩溃的原因是什么

崩溃日志/堆栈跟踪:

Exception Type:  EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x0000000000000010
Crashed Thread:  0  Dispatch queue: com.apple.main-thread

Application Specific Information:
objc_msgSend() selector name: drawerDidOpen:

Thread 0 Crashed:  Dispatch queue: com.apple.main-thread
0   libobjc.A.dylib                 0x00007fff8272011c objc_msgSend + 40
1   com.apple.Foundation            0x00007fff87d0786e _nsnote_callback + 167
2   com.apple.CoreFoundation        0x00007fff831bcaea __CFXNotificationPost + 954
3   com.apple.CoreFoundation        0x00007fff831a9098 _CFXNotificationPostNotification + 200
4   com.apple.Foundation            0x00007fff87cfe7d8 -[NSNotificationCenter postNotificationName:object:userInfo:] + 101
5   com.apple.AppKit                0x00007fff8512e944 _NSDrawerObserverCallBack + 840
6   com.apple.CoreFoundation        0x00007fff831d40d7 __CFRunLoopDoObservers + 519
7   com.apple.CoreFoundation        0x00007fff831af8c4 CFRunLoopRunSpecific + 548
8   com.apple.HIToolbox             0x00007fff839b8ada RunCurrentEventLoopInMode + 333
9   com.apple.HIToolbox             0x00007fff839b883d ReceiveNextEventCommon + 148
10  com.apple.HIToolbox             0x00007fff839b8798 BlockUntilNextEventMatchingListInMode + 59
11  com.apple.AppKit                0x00007fff84de8a2a _DPSNextEvent + 708
12  com.apple.AppKit                0x00007fff84de8379 -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] + 155
13  com.apple.AppKit                0x00007fff84dae05b -[NSApplication run] + 395
14  com.apple.AppKit                0x00007fff84da6d7c NSApplicationMain + 364
15  (my app's identifier)           0x0000000100001188 start + 52
编辑:澄清一下:在几乎相同的使用场景中,此崩溃发生过数千次甚至数万次。我不会在代码中的任何地方保留/释放/alloc/dealloc/任何内存管理委托对象;我没有在我的代码中注册任何类型的抽屉通知的任何对象;我的代码没有指向委托对象的变量(或IVAR)


在我看来,当NIB被卸载时(就像Cocoa系统在文档窗口关闭时所做的那样),抽屉的委托对象在抽屉对象本身之前被释放,但Cocoa系统应该防止这种情况发生(在绝大多数情况下似乎都能正确处理)。

委托已被释放到解除分配点,而无需首先从通知中心注销(在本例中,委托是通过通知中心进行的,而不是直接进行)

一个简单的解决方法是从代理的
-dealoc
方法调用
NSNotificationCenter的
-removeObserver:
方法


检查回溯——崩溃是通过通知中心发生的。最有可能的情况是,当类通过
setDelegate:
(通过NIB文件)连接时,它作为通知观察者进行连接

无论如何,notification center和您的对象之间的关系与IB中的对象和您的对象之间的关系相同;弱。也就是说,没有
retain
,因此,您的代理被释放得太早(或者,您在某处过度释放对象)


在任何情况下,您都需要确保您的委托在其有效期内被某个地方保留。

您看到
KERN\u无效地址0x0000000000000010
?这很可能意味着您的程序认为委托在那里。最明显的是,情况并非如此。是的,很明显。问题是为什么没有委托门在那里?如果代理通过
NSNotificationCenter
注册自己,我会理解(事实上,我两次检查了NSNotificationCenter注册抽屉通知的任何实例),但委托仅在NIB中实例化,并且仅由
NSDrawer
上的委托
IBOutlet
引用——也就是说,在我的代码中按原样获取委托对象指针的唯一方法是通过
[drawerObjectOfSomeWindow委托]
。关于回溯/通知中心,是的,它是通过通知中心进行的,但由于我没有要求观察,因此我不必删除观察者(即,如果对我隐藏了注册,也应该隐藏取消注册).Per在NIB中实例化的顶级对象在引用计数环境中的retain计数为1,因此我不明白委托对象为什么/如何获得dealloc'd。奇怪的是,引用的文档说我应该释放NIB中实例化的顶级对象“构建和分析”将发布标记为错误。尝试在代理的
发布中调用
setDelegate:nil
(可能您已经这样做了)。如果您通过窗口或视图控制器加载NIB,这些类将为您处理顶级发布(IIRC).是的--我应该提到,在某些委托情况下,'setDelegate:nil'有效地删除了观察者