uiimage和uibutton发布问题?

时间:2010-01-12 11:17:59

标签: iphone objective-c release

我已经在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];

}

任何想法?就像我说的,当我注释掉最后两行(释放按钮和图像)时,它可以正常工作。这是正常的还是我应该能够释放它们?

注意:我已删除了一些其他代码,以便在较小的块中显示此示例!

6 个答案:

答案 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对象已自动释放,因此您不得在您的函数中释放它。

来自Memory management guide

  

您只拥有使用自己创建的对象   名称以...开头的方法   “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];

}