【问题标题】:releasing a UILabel in dealloc crashes the app after it was retained, allocated & autoreleased在 dealloc 中释放 UILabel 会在应用程序被保留、分配和自动释放后崩溃
【发布时间】:2012-07-24 10:45:21
【问题描述】:

我的类头文件中有一个UILabel,定义为:

 `@property (nonatomic, retain) UILabel *label1;` 

它作为实例变量存在,如下所示:

 `UILabel *label1;` 

并在.m 文件中合成,但是,我使用viewDidLoad 方法:

 `label1 = [UILabel alloc] init] autorelease];`

然后我在标签上做各种事情,比如设置它的框架、文本颜色等...... 当视图控制器被释放时,应用程序在控制台中崩溃并显示此消息

 (Zombies enabled): `[CALayer release] message sent to deallocated instance` ...

应用不会崩溃:

1) 删除autorelease 字.. 或

2) 如果我没有在 dealloc 方法中释放 label1 .. 或

3) 移除 [super dealloc];来自视图控制器的 dealloc 方法。

我怎样才能正确地释放这个UILabel 而不会遇到这样的崩溃!

【问题讨论】:

  • 标签在dealloc 被调用之前已经被释放。那是因为它是一个自动释放对象。您的dealloc 正在尝试发布一个已经发布的 uilabel,它的崩溃.. 在您的问题中。您可以使用 1 或 2。
  • 但它已经保留在.h头文件的@property行中......
  • 如果我使用上述3点之一,应用程序肯定会泄漏内存
  • 分配会增加它的保留计数,然后当它被自动释放时它的减少,然后你释放一个dealloc'd对象。正如janusfidel所说。不需要把它作为一个属性,它是一个自动释放视图对象,只需要一个指针
  • 您只分配了一次标签,即在您的 viewDidLoad 中,@property(retain) 不会分配任何东西,但会告诉编译器我们希望如何处理我们的属性。

标签: iphone objective-c ios cocoa-touch


【解决方案1】:

你做得对。在 dealloc 中自动释放和释放。 但这不应该是崩溃。因为我做了同样的事情来检查。 您能否检查一下,可能是您在其他地方发布了标签。 并再次在 dealloc 中释放。

【讨论】:

  • 我已经在我的班级检查过标签没有额外的释放。
【解决方案2】:

因为您已将标签声明为保留。分配可以是

UILabel *myLabel = [[UILabel alloc] init];
// set all properties of label
self.label1 = myLabel;
[myLabel release];
myLabel = nil;

然后在 dealloc 中释放你的 label1。

[label1 release];

这是我习惯的方式,这让我的事情变得更顺利。

【讨论】:

    【解决方案3】:

    标签在调用 dealloc 之前已经释放。那是因为它是一个自动释放对象。您的 dealloc 正在尝试释放已经发布的UIlabel,它崩溃了..在您的问题中。您可以使用 1 或 2。如果您分配了一次对象,则只调用一次释放。这不是因为您在 @property 指令中将 retain 分配给您的属性会为您的对象添加 1 个保留计数,@property(retain) 不会分配任何内容,而是会告诉编译器您希望如何处理您的属性

    【讨论】:

      【解决方案4】:

      奇怪的是,当我使用 self.label1 = [[[UILabel alloc] init]autorelease];而不是 label1 = [[[UILabel alloc] init] autorelease];解决了这个问题。 dealloc 方法保持原样,没有任何变化。真的很奇怪!!

      【讨论】:

      • 是的,它会起作用。但在你的问题上,你提到你使用的是 self.label1 而不是 label1。如果你使用 self.label1,那么你必须使自动释放,否则 label1 的视网膜计数变为 2 .
      • 基本上,如果您直接设置对象引用,它会绕过设置器(以及保留),即 label1=,如果您使用属性形式 self.label1=,它会调用设置器(因此保留)。
      【解决方案5】:

      这样做你就不会为 label1 使用自动释放:

       - (void)dealloc
      {
        if(label1)
        {
          label1 = nil;
          [label1 release];
        }
        [super dealloc];
      }
      

      【讨论】:

      • 这种情况下应用会泄露内存
      猜你喜欢
      • 2012-10-11
      • 1970-01-01
      • 2011-12-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多