2013-01-09 62 views
0

我有一個lazily加載的屬性定義如下,似乎每次我像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 
+0

「似乎每次我像foo.bar一樣訪問它時都會保留」 - 因爲屬性太安全了。即使對象本身已被釋放,您也可以使用對象的屬性(前提是您已在釋放對象之前存儲屬性);這就是爲什麼getters不做'return _backingIvar;'而是'return [[_backingIvar retain] autorelease];' – 2013-01-09 20:12:41

回答

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; 
}