iOS - 我很困惑这里是如何处理内存的?
Posted
技术标签:
【中文标题】iOS - 我很困惑这里是如何处理内存的?【英文标题】:iOS - I'm confused how memory is being handled here? 【发布时间】:2011-09-27 13:04:02 【问题描述】:UIImage API 参考文档:- initWithContentsOfFile: 使用指定文件的内容初始化并返回图像对象。
- (id)initWithContentsOfFile:(NSString *)path
参数路径 文件的路径。此路径应包含标识图像数据类型的文件扩展名。返回值 一个已初始化的 UIImage 对象,如果方法无法找到文件或从其内容初始化图像,则为 nil。
考虑到这种情况,假设我有一个类,它可以是任何类的扩展。以 UIImage 为例。
@interface myImage : UIImage
BOOL isDefaultSet;
-(id)initWithDefaultImage;
@end
@implementation myImage
-(id)initWithDefaultImage
NSString *path = [[NSBundle mainBundle] pathForResource:@"someInvalidImage" ofType:@"png"];
idDefaultSet = YES;
return [self initWithContentsOfFile:path];
@end
//somewhere in other class:
NSString *path = [[NSBundle mainBundle] pathForResource:@"someInvalidImage" ofType:@"png"];
myImage *myObject = [[myImage alloc] initWithDefaultImage];
UIImage *yourObject = [[UIImage alloc] initWithContentsOfFile:path];
现在在这两种情况下,
“alloc”给出“retainCount+1”
如果
initWithDefaultImage/initWithContentsOfFile
由于某些问题返回 nil - 可以说(无效的文件路径),此内存将泄漏为
我的对象/你的对象
即使 allocation 是在 init 之前进行的,也会设置为 nil。
我已经看到许多以这种方式扩展类/接口的实现。我很困惑这里是如何处理内存的?任何人都可以分享对此的看法吗?
【问题讨论】:
我建议遵守约定,让您的课程以大写字符开头。你会让你的生活更轻松(如果你和其他人一起工作,你会避免被侮辱和殴打;-) 亲爱的 DarkDust.. 我只是在讨论这个问题。请不要这么苛刻..! 我认为 DarkDust 是在开玩笑,仅此而已。不过,DarkDust 是正确的,正如我通过艰难的方式了解到的那样,类应该大写,ivars 和方法以小写开头。 【参考方案1】:如果 [super init] 返回 nil,则返回 nil。因此控件从方法返回,并且 if (someInitializingFailed) 块将永远不会被执行,并且内存将被泄漏,因为在调用“initWithFoo”之前已经执行了 alloc
如果[super init]
返回nil
,则super的init
已经自行清理并释放了alloc
分配的内存。
来自Handling Initialization Failure:
您应该只在发生故障时调用 self 的 release 方法。如果你从调用超类的初始化程序得到 nil,你不应该也调用 release。
【讨论】:
【参考方案2】:通常对应的初始化器在返回nil
之前释放self
(新对象),如:
- (id)initWithFoo
self = [super init];
if (!self) return nil;
if (someInitializingFailed)
[self release];
return nil;
return self;
您可以假设-[UIImage initWithContentsOfFile:]
正在实现相同的模式。因此,除非 Instruments 确实告诉您存在泄漏,否则您不需要对您的情况进行任何特殊处理。
【讨论】:
在这种情况下也可以看到。如果 [super init] 返回 nil,则返回 nil。因此控件从方法返回,并且 if (someInitializingFailed) 块将永远不会被执行,并且内存将被泄漏,因为在调用“initWithFoo”之前已经执行了 alloc。 如果我替换 -> 返回 [self initWithContentsOfFile:path]; with -> return [super initWithContentsOfFile:path];那么它会是正确的吗? @samfisher 如果[super init]
返回nil
,则super 的init
已经自行清理并释放alloc
分配的内存。在other words 中,“你应该只在失败点调用 self 的 release 方法。如果你从调用超类的初始化程序得到 nil ,你不应该也调用 release。”
感谢@albertamg 这就是我正在寻找的解释。您可以将其发布为答案以便我接受吗?【参考方案3】:
您是对的,有时人们会忘记处理这种泄漏。如果我们无法继续初始化,则需要释放分配的内存。
-(id)initWithDefaultImage
NSString *path = [[NSBundle mainBundle] pathForResource:@"someInvalidImage" ofType:@"png"];
if (path != nil)
self = [super initWithContentsOfFile:path];
else // cannot proceed with init
[self release];
self = nil;
return self;
【讨论】:
一开始已经完成了init,怎么调用initWithContentsOfFile呢?以上是关于iOS - 我很困惑这里是如何处理内存的?的主要内容,如果未能解决你的问题,请参考以下文章