2

我对 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++;
     }];

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

如果有人可以帮助我,我将不胜感激!谢谢!

4

3 回答 3

2

您的问题是,当您生成新的时,您不会删除您subviews的 - 确保您使用以下内容删除subviews之前的内容:

NSArray *viewsToRemove = [self.contentView subviews];
for (NSView *v in viewsToRemove) {
    [v removeFromSuperview];
}

所以你的问题与实际的使用无关ARC。每次您创建一个NSImageView并将其添加到 contentView 时,您有责任在添加一系列新的之前删除它们。请注意,将这些视图添加到contentView将增加ref count1 并将它们从 contentView 中删除将使引用计数减少 1 导致系统释放这些视图的内存使用量(因为顺便说一句,没有其他东西可以保留您的视图)。

于 2012-10-23T21:22:42.740 回答
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];
于 2012-10-23T21:21:29.897 回答
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 方法中的纯代码添加到程序中的某个地方不能解决问题。现在我基本上也在做同样的事情,只是调用这个方法。

于 2012-10-25T01:01:20.810 回答