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と が 1 増加ref countし、 contentView から削除すると ref カウントが 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 に答える