【问题标题】:iOS - I'm confused how memory is being handled here?iOS - 我很困惑这里是如何处理内存的?
【发布时间】: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 和方法以小写开头。

标签: iphone objective-c ios ipad ios4


【解决方案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呢?
    猜你喜欢
    • 2017-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-04
    • 2011-04-11
    • 2014-01-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多