0

以下のように定義された遅延ロードされたプロパティがあります。これは、のようにアクセスするたびに保持されるようfoo.barです。「for」ループが終了すると (init から非同期でディスパッチされます)、すべてのコピーがbar解放されますが、その間にすべてのコピーが蓄積され、メモリ警告が表示されます。

なぜこうなった?ARC は、未使用のメモリをクリーンアップするために内部で [プールのドレイン] をヒットすることはありませんか? それとも、ディスパッチまたはブロックで保持サイクルを何らかの形で引き起こしていますか?

@interface Foo : NSObject

@property (nonatomic, strong) MyAlgorithm *bar;

@end

@implementation Foo

- (id)init {

   if (self = [super init]) {

    __weak Foo *weakSelf = self;

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        weakSelf.testAudioFilePaths = [[NSBundle mainBundle] pathsForResourcesOfType:kAudioFileWavType inDirectory:kTestFilesDirectory];

        for (NSString *path in weakSelf.testAudioFilePaths) {

            weakSelf.bar = nil; // this is so we rebuild it for each new path

            [weakSelf readDataFromAudioFileAtPath:path];

        }

    });
  }
  return self;
}

- (MyAlgorithm *)bar {
   if (!_bar) {
      _bar = [[MyAlgorithm alloc] initWithBar:kSomeBarConst];
   }
   return _bar;
}


@end
4

1 に答える 1

0

答えは、ループ内のコードのビットを@autoreleasepoolブロックでラップすることです。これにより、ループが終了した後の将来の時点ではなく、ループの反復ごとにプールがドレインされます。

- (id)init {

   if (self = [super init]) {

    __weak Foo *weakSelf = self;

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        weakSelf.testAudioFilePaths = [[NSBundle mainBundle] pathsForResourcesOfType:kAudioFileWavType inDirectory:kTestFilesDirectory];

        for (NSString *path in weakSelf.testAudioFilePaths) {

            @autoreleasepool {

                weakSelf.bar = nil; // this is so we rebuild it for each new path

                [weakSelf readDataFromAudioFileAtPath:path];
            }

        }

    });
  }
  return self;
}
于 2013-01-17T10:02:17.730 に答える