2010-10-07 2 views
0

Я архивирую массив (NSMutableArray) пользовательских объектов, которые реализуют. Как только я загружу его из файла в сохраняющее свойство @property (nonatomic, keep) NSMutableArray * buddies; количество релизов объекта равно 2 (правильно, это 1 autorelease + 1 удержания свойства), но затем никто не отпускает его, а счет сохранения составляет 1, поэтому, когда я его выпускаю, я получаю - [__ NSArrayM retainCount]: сообщение отправлен высвобождены примеру (я думаю, потому что 1 сохраняют отсчет в autorelease)iPhone NSMutableArray и NSKeyedUnarchiver unarchiveObjectWithFile release oddity

Вот полный код:

BuddieListViewController.h

#import <UIKit/UIKit.h> 
#import "Buddie.h" 

@interface BuddieListViewController : UITableViewController { 
    IBOutlet NSMutableArray *buddies; 
    [...] 
} 
[...] 
@property (nonatomic, retain) NSMutableArray *buddies; 
[...] 
@end 

BuddieListViewController.m

#import "BuddieListViewController.h" 
#import "Buddie.h" 
#import "PreviewViewController.h" 

@implementation BuddieListViewController 

@synthesize buddies; 
[...] 
- (id)initWithStyle:(UITableViewStyle)style 
{ 
    self = [super initWithStyle:style]; 
    if (self) { 
     [self loadFromDisk]; 
    } 
    return self; 
} 

- (void)loadFromDisk { 
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
    NSString *documentsPath = [paths objectAtIndex:0]; 
    NSString *appFile = [documentsPath stringByAppendingPathComponent:@"BuddieArchive.ark"]; 
    NSFileManager *fileManager = [NSFileManager defaultManager]; 
    if ([fileManager fileExistsAtPath:appFile]) { 
     self.buddies = [NSKeyedUnarchiver unarchiveObjectWithFile:appFile]; 
     NSLog(@"1- buddies retain count %d (should be 2, 1 + 1autorelease)", [buddies retainCount]); 
    } else { 
     self.buddies = [NSMutableArray arrayWithCapacity:1]; 
    } 
} 
[...] 
- (IBAction)cancelledBuddie:(NSNotification *)notification 
{ 
    [editingBuddie release]; 
    NSLog(@"2- buddies retain count %d (should be 2, 1 + 1autorelease)", [buddies retainCount]); 
    [buddies release]; 
    [self loadFromDisk]; 
    [self.tableView reloadData]; 
} 

У кого-нибудь есть представление о том, почему это происходит?

+0

Я уверен, что вы редактируете его прямо сейчас, но код немного трудно прочитать. – jps

+0

Выпускается ли это методом '-dealloc'? – jps

ответ

1

Если вам нужно обнулить массив, используйте свойство аксессор, чтобы установить его в nil:

self.buddies = nil; 

Синтезированная реализация заботится о вопросах управления памятью. Старайтесь не отправлять сообщения -retain/-release непосредственно в переменные экземпляра, где это возможно, и вместо этого позволить аксессуарам свойств позаботиться о вас. Это сэкономит вам массу неприятностей.

+0

Значит, вы говорите, что установка его на ноль автоматически освободит его из-за синтезированного аксессуар/сеттера, правильно? – w4nderlust

+0

Да, метод синтезированного сеттера отправляет сообщение '-release' объекту, который в настоящее время ссылается на переменную экземпляра, перед назначением нового значения, которое он сохраняет. – jlehr

2

Я не могу сказать, что это лучше, чем это:

The number returned by retainCount is useless.

Не полагайтесь на него что-нибудь. Используйте инструмент «Утечки» в «Инструменты», чтобы определить, протекаете ли вы объекты.


Если вы терпите крах, скорее всего, у вас есть зомби. См. this video, чтобы узнать, как использовать Инструменты для поиска зомби.

0

Вместо того чтобы освобождать друзей, не просто делать [self.buddies removeAllObjects] в начале loadFromDisk.