我已经在objective-c中编写了一段时间并且对此感到满意......但有一件事让我望而却步。内存管理。我正在发布,因为我认为是正确的,但是这段代码正在抛出“EXC_BAD_ACCESS”并崩溃了应用程序。
当我注释掉并且不释放按钮和图像时,它工作正常。调用该函数以读取图像文件名数组。
for (x=items_start;x<items_stop;x++) {
UIButton *button;
UIImage *buttonImage;
buttonImage = [UIImage imageNamed:[NSString stringWithFormat:@"%i.png", x]];
button = [UIButton buttonWithType:UIButtonTypeCustom];
button.tag = x;
[button setImage:buttonImage forState:UIControlStateNormal];
[button addTarget:self action:@selector(duplicateImage:) forControlEvents:UIControlEventTouchUpInside];
[viewBasicItems addSubview:button];
[buttonImage release];
[button release];
}
任何想法?就像我说的,当我注释掉最后两行(释放按钮和图像)时,它可以正常工作。这是正常的还是我应该能够释放它们?
注意:我已删除了一些其他代码,以便在较小的块中显示此示例!
答案 0 :(得分:6)
button
的实例已自动释放:
button = [UIButton buttonWithType:UIButtonTypeCustom];
您使用的是便捷方法+buttonWithType:
,而不是alloc/init
对。所以你的应用程序也会在这里崩溃:
[button release];
删除-release
语句或使用alloc/init
实例化按钮视图。
我建议您使用alloc/init
,因为您在for
循环中执行了所有这些操作。您可能在该循环中构建了许多需要自动释放的对象。手动分配内存并释放它可能更好。
并阅读Apple的memory management guide。
答案 1 :(得分:4)
buttonImage = [UIImage imageNamed:[NSString stringWithFormat:@"%i.png", x]];
您的buttonImage
对象已自动释放,因此您不得在您的函数中释放它。
您只拥有使用自己创建的对象 名称以...开头的方法 “alloc”或“new”或包含“copy” (例如,alloc,newObject或 mutableCopy),或者如果你发送它 保留信息。
编辑:当Alex指出你的按钮对象也是自动释放的。
答案 2 :(得分:0)
您有三种选择:
使用alloc / init 例如;
NSString *imagePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingString:[NSString stringWithFormat:@"/%i.png",x]];
buttonImage = [[UIImage alloc] initWithContentsOfFile:imagePath];
并在完成后释放
[buttonImage release];
或使用保留/复制
buttonImage = [[UIImage imageNamed:[NSString stringWithFormat:@"%i.png", x]] retain ];
并释放它
[buttonImage release];
或者像你一样使用Autoreleased对象但不释放它,因为它们会自动释放。 您应该像其他人一样阅读Apple内存管理指南。
答案 3 :(得分:0)
好的,基础知识。
创建对象的大多数方法都会返回已分配的对象,然后“自动释放”。
autorelease调用将您的对象添加到“自动释放池”,这意味着他们将在您的应用程序访问事件循环时收到释放调用。
使用自动释放的对象时,可以使用它们,然后忘记它们。它们会自动释放。
正如其他人所说的那样,例外是名称中包含“init”或“new”的调用,或者调用“复制”方法。这些方法返回尚未自动释放的对象。这些对象的所有者需要释放或自动释放这些对象才能释放它们,并且不会导致内存泄漏。
在示例代码中,使用调用+ imageNamed和+ buttonWithType创建buttonImage和button对象。
这些是返回所需类型对象的类调用。由于它们的名称中不包含“init”或“new”,因此它们返回的对象已经自动释放,因此您不应该释放它们。
您将创建的图像传递给按钮,因此按钮会保留图像。然后使用-addSubview调用将按钮对象传递给viewBasicItems对象,以便视图保留按钮。
因此,你不应该做任何其他事情。该按钮将保留图像,视图将保留按钮。
我希望有所帮助。
答案 4 :(得分:0)
这不是一个使用[UIButton ButtonWithType:]的好方法..因为你不能释放对象......而不是这个jus使用
`for (x=items_start;x<items_stop;x++) {
UIButton *button;
UIImage *buttonImage;
buttonImage = [UIImage alloc] initWithContentOfFile:[[[NSBundle mainBundle] resourcePath] stringByAppendingString:[NSString stringWithFormat:@"/%i.png",x]]];
button = [[UIButton alloc] init];
button.tag = x;
[button setImage:buttonImage forState:UIControlStateNormal];
[button addTarget:self action:@selector(duplicateImage:) forControlEvents:UIControlEventTouchUpInside];
[viewBasicItems addSubview:button];
[buttonImage release];
[button release];
}
`
答案 5 :(得分:0)
按以下方式修复代码:
for (x=items_start;x<items_stop;x++) {
UIButton *button;
button = [UIButton buttonWithType:UIButtonTypeCustom];
button.tag = x;
[button setImage:[UIImage imageNamed:[NSString stringWithFormat:@"%i.png", x]]
forState:UIControlStateNormal];
[button addTarget:self action:@selector(duplicateImage:)
forControlEvents:UIControlEventTouchUpInside];
[viewBasicItems addSubview:button];
[button release];
}