iPhone NSMutableArray和NSKeyedUnarchiver unarchiveObjectWithFile释放奇怪

时间:2010-10-07 19:52:15

标签: ios memory-management nsmutablearray autorelease

我归档了一个实现自定义对象的数组(NSMutableArray)。 一旦我将文件从文件加载到保留属性 @property(nonatomic,retain)NSMutableArray *好友; 对象的释放计数是2(正确,它是自动释放的1和保留属性的1)然后没有人释放它并且保留计数成为1,所以当我释放它时我得到 - [__ NSArrayM retainCount]:发送给解除分配实例的消息 (我认为因为1保留计数是自动释放)

这是完整的代码:

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

有谁知道为什么会这样?

3 个答案:

答案 0 :(得分:2)

我不能说比这更好:

  

The number returned by retainCount is useless.

不要依赖它。使用“仪器”中的“泄漏”工具确定是否泄漏了对象。


如果你正在崩溃,那么你最有可能拥有一个僵尸。请参阅this video以了解如何使用Instruments查找僵尸。

答案 1 :(得分:1)

如果您需要使数组无效,请使用属性访问器将其设置为nil

self.buddies = nil;

合成的实现处理内存管理问题。尽量避免在可能的情况下直接向实例变量发送-retain/-release消息,而是允许属性访问者为您处理事情。它会为你省去很多麻烦。

答案 2 :(得分:0)

而不是释放好友为什么不在loadFromDisk的开头做一个[self.buddies removeAllObjects]。