【问题标题】:Objects deallocation question对象释放问题
【发布时间】:2011-07-04 00:21:05
【问题描述】:

我有一个代码:

@interface PhotoListViewController : UIViewController 
{
    IBOutlet UIImageView* firstPicContainer;
    IBOutlet UIImageView* secondPicContainer;
    UIImage* pic_one;
    UIImage* pic_two;
    IBOutlet UILabel* firstPicLabel;
    IBOutlet UILabel* secondPicLabel;
    NSString* firstPicName;
    NSString* secondPicName;
    IBOutlet UILabel* authorLabelA;
    IBOutlet UILabel* authorLabelB;
    NSString* authorName;

}
@property (retain) UIImage* pic_one;
@property (retain) UIImage* pic_two;
@property (copy) NSString* firstPicName;
@property (copy) NSString* secondPicName;
@property (copy) NSString* authorName;


@end

问题是:我应该释放整个对象包还是只释放那些我已声明其属性的对象? 例如:firstPicName为NSString并被保留,设置时其容器为UILabel* firstPicLabel,赋值如下:

firstPicLabel.text = firstPicName;

在 -viewDidLoad 中。所以标签作为一个对象不会被自己保留,它的属性会。其他对象也是如此,保留属性,其他只是一个容器。这些容器的所有者是他们的观点,应该对它们的释放负责,但我在这里有点困惑,所以我想澄清这一点。 谢谢。

【问题讨论】:

  • 请不要在 ivar 名称或方法名称中使用下划线;与常规相比,它看起来格格不入。

标签: objective-c ios memory-management dealloc


【解决方案1】:

简短回答:对于您声明为retain(或copy)的任何属性,您应该在dealloc 方法中将其值设置为nil。在您自己不保留的其他对象和字段上声明的属性无需担心。

【讨论】:

  • 嗯,这不完全是我要的:)
  • 那么,我不需要担心那些标签和 UIImageViews 吗?它们的属性是由这些声明的属性的值分配的,并且因为它们是分配的,所以它们不应该被显式释放?
  • @Matubo - 那我不确定你要什么。我以为你想知道你需要释放哪些对象?如果是这样,那么答案是“只有您声明为保留/复制的属性,以及您在代码中手动保留的任何其他对象”。
  • 我的回复是关于你的第一个版本的答案,没有第二个短语。 :)
  • 你也可以不用担心差异,在你的 dealloc 中将所有属性设置为 nil。如果它们被设置为保留或复制,那么这将导致设置器释放它们。如果它们被设置为分配,那么设置器将不会对内存管理做任何事情。
【解决方案2】:

你的界面永远不会提供关于你应该或不应该发布什么的足够信息(但它会提供线索)。

您可以拥有上面声明的所有 ivars 和属性,但如果您没有初始化它们和/或访问它们的属性,那么一开始就永远不会释放对象。

经验法则是:

1) 如果您创建、复制或保留对象,您有责任释放它。

2) 参见上面的规则 #1。

在实践中,这里有一些例子:

@implementation...
...
pic_one = [UIImage imageNamed:@"test.png"];
...
@end

pic_one 被声明为 ivar,但被分配给自动释放的对象。你不必释放它。

另一个例子:

@implementation....
...
self.pic_one = [UIImage imageNamed:@"test.png"];
...
@end

您通过声明为保留的评估器/属性分配了此 UIImage 对象,因此您有责任释放它。 “幕后”,当您通过其属性分配对象时会发生以下情况(例如,对于声明为保留的属性,复制将略有不同但原理相同)。

- (void)setPic_One:(UIImage*)newImage
{
   if (pic_One != newImage)
   {
        [newImage retain];
        [pic_One release];
        pic_One = newImage;
   }
}

最后一个:

UIImage *testImage = [[UIImage alloc] initWithImage:@"test.png"];
self.pic_one = testImage;
[testImage release];

在这种情况下,您正在分配/初始化(创建)一个 UIImage 对象,因此您负责释放它。同时,您还将它分配给声明为保留的属性,因此您也有责任在使用完它时释放它(通常在您的 dealloc 方法中)。

【讨论】:

  • 是的,这些是内存管理的基础知识,对于每个初学者来说都是 ABC。但此刻,我想澄清的是:firstPicContainer.image = self.pic_one; UIImageView 在 iVar 中声明,它的属性被分配给一个保留值。然后应该在 -dealloc 中释放它吗?
  • 问题出在情况的二元性:一方面属性值由我保留,UIImageView的属性'image'由我自己保留:'@property(nonatomic, retain) UIImage *图片'。一切都表明,我应该释放它。但另一方面:我没有打破内存规则:从未使用'alloc''copy''new'函数来创建实例。并且 UIImageView 作为它的子视图归视图所有,所以视图负责释放它,我不应该。我真的很绝望。
  • 回答您的第一条评论:firstPicContainer.image = self.pic_one,不应释放 firstPicContainer,因为您不是通过其属性而是直接通过 ivar 访问它。但是因为 firstPicContainer 也被声明为 IBOutlet,当你的 nib 被加载时它会被视图保留(如果你已经将它连接到 Interface Builder 上的 UIImageView 对象)。在这种情况下,您必须释放firstPicContainer,因为接口生成器将通过其属性访问它(还建议您在viewDidUnload 上将其设置为nil)。
  • 除了上面的评论之外,您可能应该发布一个带有接口和实现文件的示例,以澄清您的要求。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多