NSOpenPanel 和检测到泄露的观察者

Posted

技术标签:

【中文标题】NSOpenPanel 和检测到泄露的观察者【英文标题】:NSOpenPanel and detected leaked observer 【发布时间】:2016-01-21 08:05:22 【问题描述】:

在我的程序执行过程中,我收到了来自 XCode 的警告:

2016-01-21 03:19:26.468 IsoMetadonnees[1975:303] An instance 0x1004eefd0 of class NSVBOpenPanel was deallocated while key value observers were still registered with it. Observation info was leaked, and may even become mistakenly attached to some other object. Set a breakpoint on NSKVODeallocateBreak to stop here in the debugger. Here's the current observation info:
  <NSKeyValueObservationInfo 0x608000444710> (
  <NSKeyValueObservance 0x6080000d5310: Observer: 0x100592cf0, Key path: level, Options: <New: YES, Old: NO, Prior: NO> Context: 0x0, Property: 0x6080004486a0>
  )

当应用程序显示一个 NSOpenPanel 来选择一些将被异步加载的文件时,就会出现问题。应用程序不会崩溃并且文件已正确加载...

我没有创建任何值观察者,所以我认为观察者是由 NSOpenPanel 创建的,但我不知道有什么程序可以删除我没有创建的观察者...

尽管有这个警告,我还是做了多次加载,没有注意到任何崩溃。我多年来一直使用我的应用程序,没有任何问题,但我最近切换到 ARC;可能是此时出现(或检测到)问题。

这是我的代码的简化版本:

- (IBAction)ajoutFichier:(id)sender 
    NSOpenPanel  *openPanel = [NSOpenPanel openPanel];
    // Here some configurations of openPanel

    if ([openPanel runModal] == NSOKButton) 
        tmp_listeURLFichiers = [openPanel URLs];
    
    //[openPanel close]; // I add this code unsuccessfully
    openPanel = nil; // I add this code unsuccessfully

    // I call a task in back ground to load my files
    if ((tmp_listeURLFichiers != nil) && ([tmp_listeURLFichiers count]>0))
        [self performSelectorInBackground:@selector(ajouteListeFichiers:) withObject:tmp_listeURLFichiers];


// Load files in background
-(BOOL) ajouteListeFichiers:(NSArray *)listeDesFichierAAjouter 
    @autoreleasepool 
        // Some stuff to show a progress bar

        // Loop to load selected files
        for (id tmpCheminVersMonImage in listeDesFichierAAjouter) 
            // Load files
        


       //  <========== THE WARNING OCCURS AT THIS POINT, WHEN autoreleasepool is cleaned
    return (YES);
       

我尝试添加

[openPanel close]; 

openPanel = nil;

在启动后台任务之前强制从内存(以及观察者)中释放 openPanel,但这不会改变任何东西......

你有什么想法吗?

感谢您的帮助!

【问题讨论】:

什么是NSVBOpenPanel?你添加任何观察者吗?您是否在 NSKVODeallocateBreak 上设置了断点并 po 观察者? 我不知道 NSVBOpenPanel 是什么...我只使用 NSOpenPanel。当我们使用沙箱时,我猜 NSVBOpenPanel 是一种 NSOpenPanel。我按照警告告诉我的方式设置了一个断点,并且我可以在我的第一篇文章中确定警告发生在自动释放池的排水管(我在代码中指出的点)处。而且我没有添加任何观察者... 【参考方案1】:

我可以使用以下技巧解决问题:

我在视图控制器中声明了一个变量:

__strong NSOpenPanel  *prgOpenPanel;

然后我在我的代码中使用它

//NSOpenPanel  *prgOpenPanel = [NSOpenPanel openPanel];
self.prgOpenPanel = nil;
self.prgOpenPanel = [NSOpenPanel openPanel];
// Here some configurations of openPanel

if ([prgOpenPanel runModal] == NSOKButton) 
    tmp_listeURLFichiers = [prgOpenPanel URLs];
    if ((tmp_listeURLFichiers != nil) && ([tmp_listeURLFichiers count]>0))
        [self performSelectorInBackground:@selector(ajouteListeFichiers:) withObject:tmp_listeURLFichiers];

没有更多警告!

【讨论】:

以上是关于NSOpenPanel 和检测到泄露的观察者的主要内容,如果未能解决你的问题,请参考以下文章

内存泄露检测工具Valgrind

在 Chrome Devtools 中检测和观察对样式表所做的更改

观察 NSArrayController 变化:检测插入或删除

我可以在后台观察来电和去电吗?

设计模式观察者模式

如何让突变观察者检测文本区域的值变化?