NSImageView未使用ARC取消分配

时间:2012-10-23 20:32:50

标签: objective-c macos cocoa nsimageview

我对Cocoa开发很新,我可能不清楚ARC是如何工作的。

我的问题是,当我使用NSImageView时,它并没有像我想要的那样被释放,因此程序正在泄漏内存。

__block CMTime lastTime = CMTimeMake(-1, 1);
__block int count = 0;
[_imageGenerator generateCGImagesAsynchronouslyForTimes:stops
                                      completionHandler:^(CMTime requestedTime, CGImageRef image, CMTime actualTime,
                                                                AVAssetImageGeneratorResult result, NSError *error)
     {
         if (result == AVAssetImageGeneratorSucceeded)
         {
             if (CMTimeCompare(actualTime, lastTime) != 0)
             {
                 NSLog(@"new frame found");
                 lastTime = actualTime;
             }
             else
             {
                 NSLog(@"skipping");
                 return;
             }

             // place the image onto the view
             NSRect rect = CGRectMake((count+0.5) * 110, 100, 100, 100);

             // the problem is here!!! ImageView object gets allocated, but never released by the program even though I'm using ARC 

             NSImageView *imgV = [[NSImageView alloc] initWithFrame:rect];

             [imgV setImageScaling:NSScaleToFit];
             NSImage *myImage = [[NSImage alloc] initWithCGImage:image size:(NSSize){50.0,50.0}];
             [imgV setImage:myImage];
             [self.window.contentView addSubview: imgV];
         }

         if (result == AVAssetImageGeneratorFailed)
         {
             NSLog(@"Failed with error: %@", [error localizedDescription]);
         }
         if (result == AVAssetImageGeneratorCancelled)
         {
             NSLog(@"Canceled");
         }
         count++;
     }];

因此,当我再次返回此块时,生成新图像并显示它们,一切都很完美,除了我的程序内存使用量增加了创建的视图数量。

如果有人可以帮助我,我会非常感激!谢谢!

3 个答案:

答案 0 :(得分:2)

您的问题是,当您生成新的subviews时,请不要删除subviews - 请务必先删除NSArray *viewsToRemove = [self.contentView subviews]; for (NSView *v in viewsToRemove) { [v removeFromSuperview]; } 之前的某些内容:

ARC

因此,您的问题实际上与NSImageView的使用无关。每次创建contentView并将其添加到contentView时,您都有责任在添加一系列新内容之前删除它们。请注意,将这些视图添加到ref count会将{{1}}递增1并将其从contentView中删除会将ref计数减1,从而导致系统释放这些视图的内存使用量(因为没有否则在btw中保留你的观点。

答案 1 :(得分:1)

违规代码:

[self.window.contentView addSubview: imgV];

您已经分配了NSImageView。并继续将其添加到视图中。你永远不会删除它,这意味着视图创建了许多对同一对象的不同实例的引用,都分配了自己的内存。

解决方案:您需要跟踪视图,以确保以后可以将其删除。通常,我使用类扩展。

例如:

@interface ClassName() {
    NSImageView* m_imgV;
}
@end

....

// place the image onto the view
NSRect rect = CGRectMake((count+0.5) * 110, 100, 100, 100);

if (m_imgV) {
    [m_imgV removeFromSuperView];
}
m_imgV = [[NSImageView alloc] initWithFrame:rect];

[m_imgV setImageScaling:NSScaleToFit];
NSImage *myImage = [[NSImage alloc] initWithCGImage:image size:(NSSize){50.0,50.0}];
[m_imgV setImage:myImage];
[self.window.contentView addSubview:m_imgV];

答案 2 :(得分:0)

我整天都在与这个问题作斗争,终于找到了方法。出于某种原因,该程序希望我添加一个完整的函数,如下所示:

// remove all the view from the superview
// and clean up a garbage array
-(void) killAllViews
{
   for (NSImageView *iv in _viewsToRemove)
   {
      [iv removeFromSuperview];
   }
   [_viewsToRemove removeAllObjects]; // clean out the array
}

其中_viewsToRemove是一个NSImageViews数组,每当我的块生成新图像并将它们添加到视图中时,我就会填充它们。

仍然不明白为什么只是将我的killAllViews方法中的纯代码添加到程序中就无法解决问题。现在我基本上做同样的事情,但只是调用这个方法。