我们必须保留由非ARC中的方法返回的对象吗



考虑一下在Manual Retain Release中实现的一种情况,其中我有一个变量指向一个方法返回的对象。

{
...
NSString *str = [self myNewString];
...
}
- (NSString *)myNewString
{
NSString *myString = [NSString stringWithFormat:@"%d-String", 1];
return myString;
}

在这里,我们必须保留myNewString返回的对象,以便在使用时不会释放它吗?

请帮帮我,我是Objective-C的新手。提前谢谢。

这个答案有两个方面:

  1. 首先,您希望遵守方法命名规则,该规则规定任何名称以"alloc"、"new"、"copy"或"mutableCopy"开头的方法都应具有+1保留计数(即所有权转移),否则,它应该是一个autorelease对象(或者,更准确地说,是所有权未转移的任何对象,如果调用者想要声明所有权,则必须手动retain它)。

    顺便说一句,ARC使用这些方法名称前缀来自动确定对象内存语义,但在手动保留和释放(MRR)代码中,程序员有责任确保方法的内存管理符合方法名称所隐含的语义。如果您将来将此MRR代码与ARC代码集成,那么遵循此方法命名规则将变得非常重要。如果您的遗留代码违反了此方法命名约定,则可以使用一些代码提示,但最好确保代码的内存语义符合此方法命名规则。

    无论如何,此方法命名规则包含在高级内存管理编程指南中概述的基本内存管理规则中

    因此,在手动保留和释放中,您有两种选择之一。如果该方法以"alloc"、"new"、"copy"或"mutableCopy"开头,那么它应该通过返回+1retainCount对象来转移所有权,例如:

    - (NSString *)newSomeString
    {
    return [[NSString alloc] initWithFormat:@"%d-String", 1];
    }
    

    否则,它不应该转移所有权(例如,返回一个autorelease对象),例如:

    - (NSString *)someString
    {
    return [NSString stringWithFormat:@"%d-String", 1];
    }
    
  2. 因此,如果调用者想确保对象被保留,它可以只调用返回+1对象的方法:

    NSString *string = [self newSomeString];
    

    或者,调用返回autorelease对象的版本,但随后显式地调用retainit:

    NSString *string = [[self someString] retain];
    

在实践中,后一种约定,即someString示例,更为常见(使用返回autorelease对象的方法,即方法名称不以"alloc"、"new"、"copy"或"mutableCopy"开头的方法;然后,如果调用方需要retain,则应显式执行此操作)。newcopymutableCopy方法通常都在各自非常特定的上下文中使用,这些上下文在此不适用。

顺便说一句,如果你通过静态分析器(Xcode的"产品"菜单上的"分析")运行你的代码,如果你的MRR代码存在过度保留对象或无法保留对象的问题,它会很好地警告你。

但最重要的是,请仔细遵循基本的内存管理规则,包括命名方法的约定,然后如果需要保留它,请显式地retain您的autorelease对象或调用返回+1retainCount对象的方法。

这里只传递存储NSString对象的位置地址。所以,对象肯定会被编译器保留。但你不必担心。一旦引用计数为0,ARC将负责释放内存。给你了解更多关于ARC 的信息

基本上,除了new/alloc+init之外,任何返回新对象的方法都会在没有所有权的情况下返回它,这意味着你可以指望它一直存在,直到封闭的自动释放池耗尽,但之后就不知道了。如果你想让它存在更长的时间,你必须保留它

最新更新