【问题标题】:uiimage and uibutton release problem?uiimage 和 uibutton 释放问题?
【发布时间】:2010-01-12 11:17:59
【问题描述】:

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

}

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

注意:我已经删除了相当多的其他代码,以便以较小的块显示此示例!

【问题讨论】:

    标签: iphone objective-c release


    【解决方案1】:

    button 的实例是自动释放的:

    button = [UIButton buttonWithType:UIButtonTypeCustom];
    

    您正在使用便捷方法 +buttonWithType: 而不是 alloc/init 对。所以你的应用也会在这里崩溃:

    [button release];
    

    要么删除 -release 语句,要么使用 alloc/init 实例化按钮视图。

    我建议您使用alloc/init,因为您在for 循环中执行所有这些操作。您可能会在该循环中构建许多需要自动释放的对象。手动分配内存并释放它可能会更好。

    请阅读 Apple 的 memory management guide

    【讨论】:

    • 我明白了!这就解释了。感谢您的帮助。
    【解决方案2】:
    buttonImage = [UIImage imageNamed:[NSString stringWithFormat:@"%i.png", x]];
    

    你的buttonImage 对象是自动释放的,所以你不能在你的函数中释放它。

    来自Memory management guide

    您只拥有您使用创建的对象 名称以开头的方法 “alloc”或“new”或包含“copy” (例如,alloc、newObject 或 mutableCopy),或者如果你发送一个 保留消息。

    编辑:正如 Alex 指出的那样,您的按钮对象也会自动释放。

    【讨论】:

      【解决方案3】:

      你有三个选择:

      使用分配/初始化 例如;

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

      然后释放它

      [按钮图片释放];

      或者像你一样使用自动释放的对象,但不要释放它,因为它们会自动释放。 您应该像其他人所说的那样阅读 Apple 内存管理指南。

      【讨论】:

        【解决方案4】:

        好的,基本的。

        大多数创建对象的方法都返回已分配的对象,然后是“自动释放”。

        自动释放调用会将您的对象添加到“自动释放池”,这意味着它们将在您的应用下次访问事件循环时收到释放调用。

        当您使用自动释放的对象时,您可以使用它们,然后忘记它们。它们会自动释放。

        正如其他人所说,例外情况是名称中包含“init”或“new”的调用,或对“copy”方法的调用。这些方法返回尚未自动释放的对象。这些对象的所有者需要释放或自动释放这些对象才能释放它们,并且不会导致内存泄漏。

        在您的示例代码中,您使用 +imageNamed 和 +buttonWithType 调用创建 buttonImage 和按钮对象。

        这些是返回所需类型对象的类调用。由于它们的名称中不包含“init”或“new”,因此它们返回的对象已经自动释放,因此您不应释放它们。

        您将创建的图像传递给按钮,因此按钮会保留图像。然后,您可以使用 -addSubview 调用将按钮对象传递给 viewBasicItems 对象,以便视图保留按钮。

        因此,您不应该做任何其他事情。按钮将保留图像,视图将保留按钮。

        希望对你有帮助。

        【讨论】:

          【解决方案5】:

          这不是使用 [UIButton ButtonWithType:] 的好方法..因为你不能释放对象..而不是这个只是使用

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

          【讨论】:

            【解决方案6】:

            将您的代码修复如下:

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

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2012-08-03
              相关资源
              最近更新 更多