如果我在将第一个数组复制到第二个数组后将其释放,我的应用程序崩溃了。如果我自动释放第一个阵列一切正常。为什么?有没有更好的方法将第一个数组复制到第二个数组?
如果我调用此方法,我会得到一个ECX_BAD_ACCESS,我传递一个空数组
-(NSArray *)loadSystemDetails
{
AssortedCodeSnippets *acs = [[AssortedCodeSnippets alloc] init];
NSArray *details;
NSString *fp = [self tempPathAndFileName:[self systemDetailsFileName]];
if ([acs fileExistsAtPath:fp]) {
NSArray *array = [[NSArray alloc] initWithContentsOfFile:fp];
details = array;
[array release];
} else {
NSLog(@"No File to Load");
CreateSystem *cls = [[CreateSystem alloc] init];
details = [cls loadData];
[cls release];
[self saveDataFile:details toPath:fp];
}
NSLog(@"details: %@",details);
[acs release];
return details;
}
如果我自动释放阵列,它可以正常工作。
-(NSArray *)loadSystemDetails
{
AssortedCodeSnippets *acs = [[AssortedCodeSnippets alloc] init];
NSArray *details;
NSString *fp = [self tempPathAndFileName:[self systemDetailsFileName]];
if ([acs fileExistsAtPath:fp]) {
NSArray *array = [[[NSArray alloc] initWithContentsOfFile:fp]autorelease];
details = array;
} else {
NSLog(@"No File to Load");
CreateSystem *cls = [[CreateSystem alloc] init];
details = [cls loadData];
[cls release];
[self saveDataFile:details toPath:fp];
}
答案 0 :(得分:2)
让我们逐步完成这个
密钥:M =发布/保留消息,C =发布/保留消息的总和
// +----+---+
// | M | C |
// +----+---+
NSArray *array = [[NSArray alloc] initWithContentsOfFile:fp]; // | +1 | 1 |
details = array; // | 0 | 1 |
[array release]; // | -1 | 0 |
// +----+---+
此时你可以看到你将返回details
,其数量为0,因此已经解除分配=崩溃。
复制是错误的术语,因为您实际上并不需要副本,因此您只希望指针details
指向有效对象,因此以下内容会更正确
- (NSArray *)systemDetails
{
NSString *filePath = [self tempPathAndFileName:[self systemDetailsFileName]];
NSArray *details = [[[NSArray alloc] initWithContentsOfFile:filePath] autorelease];
if (!details) {
NSLog(@"No File to Load");
CreateSystem *cls = [[CreateSystem alloc] init];
details = [cls loadData];
[cls release]; cls = nil;
[self saveDataFile:details toPath:filePath];
}
NSLog(@"details: %@",details);
return details;
}
我在这里利用NSArray的方法
initWithContentsOfFile:
... [return]如果无法打开文件或文件内容无法解析为数组,则返回
这减少了一些错误并使该方法更容易阅读。我还将变量名称扩展为有意义的名称(个人偏好)。
我还重命名了这个方法,因为load
艺术是超级的,因为基本上你正在返回系统详细信息,它们被加载的事实并不是方法调用者真正关心的事实。
同样重要的是要注意,其他答案表明您需要额外的保留/复制,然后记得稍后发布返回的结果。这违反了cocoa约定,因为方法名称不包含new / init / copy,因此方法的调用者不应该最终拥有结果。
答案 1 :(得分:1)
在分配details
指向retain
或details
的{{1}}方法的结果时,发送array
分配cls
条消息。请务必-loadData
方法之后的release
details
。
答案 2 :(得分:1)
在您的代码示例中,您实际上并未将array
复制到details
。请记住,这两个变量都是指针到数组而不是数组本身。因此,行details = array
只是将array
的位置复制到details
。换句话说,在这一行之后,两个变量都指向内存中完全相同的数组。因此,当您调用release
时,内存中的对象将被释放,而 details
和array
现在都指向一个不存在的对象。如果要将数组实际复制到内存中,请使用
details = [array copy]
请记住,当你想摆脱这个对象时,最终你必须在release
上调用details
。