命名方法的简单规则,与ARC命名约定兼容

Col*_*las 4 memory-leaks objective-c naming-conventions class-method automatic-ref-counting

我很难理解ARC的命名约定.我一直用ARC编码,我猜这就是原因.

1.类方法

  • 我应该为以下方法选择什么名称?
  • 这两个名字之间在内存管理上有什么不同?

这个名字:

+ (MyObject *)newObjectFrom:(MyObject *)anObject 
                withOptions:(NSDictionary*)options
{
    MyObject * newObject = [anObject copy] ;
    [newObject modifyWith:options] ;
    return newObject ;
}
Run Code Online (Sandbox Code Playgroud)

还是这个名字?

+ (MyObject *)objectFrom:(MyObject *)anObject
             withOptions:(NSDictionary*)options
{
    MyObject * newObject = [anObject copy] ;
    [newObject modifyWith:options] ;
    return newObject ;
}
Run Code Online (Sandbox Code Playgroud)

2.实例方法

  • 我应该为以下方法选择什么名称?
  • 这两个名字之间在内存管理上有什么不同?

这个名字:

- (MyObject *)newObjectwithOptions:(NSDictionary*)options
{
    MyObject * newObject = [self copy] ;
    [newObject modifyWith:options] ;
    return newObject ;
}
Run Code Online (Sandbox Code Playgroud)

还是这个名字?

- (MyObject *)objectwithOptions:(NSDictionary*)options
{
    MyObject * newObject = [self copy] ;
    [newObject modifyWith:options] ;
    return newObject ;
}
Run Code Online (Sandbox Code Playgroud)

2.命名方法的简单规则

在命名方法时是否有一个基本的简单规则?

我的意思是"基本的,简单的"

  • 类似于" strong当对象属于类" 时的规则," weak当该对象刚刚被该类引用,并且(因此)由另一个类拥有时";

  • (和/或)没有引用内存管理的规则ARC;

  • (和/或)不使用诸如"autorelease","release"之类的单词的规则.

Jod*_*ins 5

方法名称重要.有关ARC如何解释方法名称的官方文档可以在方法系列一节中的clang ARC文档中找到.


Ami*_*wad 5

当 Rivera 说方法名称不重要时,他可能遵循了他的经验:它总是有效的。这是正确的。您可能不了解方法名称的作用是正确的,因为您一直在使用 ARC。那么这有什么大不了的呢?

我在这个答案的末尾添加了一个概要来显示 MRR 的问题。正如您在那里看到的,您不必像使用 MRR 那样关心使用 ARC 的命名规则。

为了给您更详细的解释,您必须了解使用 MRR 会发生什么:

在 ARC 之前,必须手动进行内存管理。这样做他必须知道,返回值具有什么样的所有权。长话短说,人们必须知道,他是否必须释放返回的对象:

规则 1:您不拥有由方法自动返回的对象。如果你想保持它,保留它并释放它,当用它做。

id object = [[object methodThatReturnsAnObject] retain]; // I want to hold it
…
[object release]; // Done with it

id object = [object methodThatReturnsAnObject]; // I do not want to hold it
…
// I do not release it
Run Code Online (Sandbox Code Playgroud)

进行深入分析,您可以看到有时会出现问题。(对象释放作为副作用。)但这是基本方法。

这样做的好处是可以在本地(在复合语句内)处理一个保留-释放对,并且很容易跟踪对象的所有权。

规则 2:但是当第一次创建对象时,这不起作用:消息的发送者必须始终持有它。否则它会立即被销毁(= 在发件人有机会保留它之前。)所以有一个额外的规则:

如果返回对象的类方法的名称以 alloc、init 或 new 开头,则必须像在其上执行保留一样处理返回的对象。或者一句话:所有权转让:

id object = [Class allocOrInitOrNewMethod];
…
[object release];
Run Code Online (Sandbox Code Playgroud)

由于-retain明确地取得了所有权,alloc–, init…new…隐式地转让了它。

所有其他方法的行为类似于规则 1。

规则 3:有时你需要一个自动释放池。为了让ARPs的优势可见,想到这段代码:(没用,只是为了演示问题

案例 1.1:

Person *person = [[Person alloc] initWithName:…]; // Ownership transfer, release person, when you are done
NSString *name = [person name]; // the name object is hold by the person object only
[person release]; // I do not need the person object any more
[name doSomething]; // Crash: The person was the only object holding the name
Run Code Online (Sandbox Code Playgroud)

另一个问题:

案例 2.1:

Person *person = [[Person alloc] initWithName:…]; // Ownership transfer, release person, when you are done
if (…)
{
   return; // break, continue, goto
}
…
[person release];
Run Code Online (Sandbox Code Playgroud)

因为永远不会到达最后一行,所以永远不会释放该对象。

您可以使用自动释放方法修复它。只要控制流返回到运行循环,移动到 ARP 的对象就会存在。所以它存在于每个方法中,通过方法返回等等。要明确地做到这一点:

案例 1.2:

Person *person = [[[Person alloc] initWithName:…] autorelease]; // No ownership transfer, persons belongs to the ARP
NSString *name = [person name]; // the name object is hold by the person object only
[name doSomething]; // No Crash: The person object holding the name object is still alive
Run Code Online (Sandbox Code Playgroud)

案例 2.2:

Person *person = [[[Person alloc] initWithName:…] autorelease]; // No ownership transfer, prsons belongs to the AR.
if (…)
{
   return; // break, continue, goto
}
…
// No release necessary.
Run Code Online (Sandbox Code Playgroud)

因为懒得输入这么长的消息链,所以已经发明了便利分配器来为你做这件事:

+ (Person*)personWithName:(NSString*)name
{
   return [[[self alloc] initWithName:name] autorelease];
}
Run Code Online (Sandbox Code Playgroud)

结果:

案例 2.3:

Person *person = [personWithName:…]; // No ownership transfer, persons belongs to the AR.
if (…)
{
   return; // break, continue, goto
}
…
// No release necessary.
Run Code Online (Sandbox Code Playgroud)

你可以对 getter 做同样的事情:

- (NSString*)name
{
   return [[_name retain] autorelease];
}
Run Code Online (Sandbox Code Playgroud)

所以我们在一天结束时有简单的规则:

规则 1:如果您想将返回的对象保留在内存中,请保留它——并在您不再需要它时释放它。

规则 2:如果类方法的名称以 alloc、new 或 init 开头,请将其视为隐式的retain(因此在您完成对象后将其释放。)

规则 3:-autorelease为了方便起见,用于延迟释放返回的对象。

概要:

alloc-init 创建

// MRR:
Person *person = [[Person alloc] initWithName:@"Amin"];
…
[person release]; // You create it, you release it

// ARC:
Person *person = [[Person alloc] initWithName:@"Amin"];
…
Run Code Online (Sandbox Code Playgroud)

新创作者

// MRR:
Person *person = [[Person newPersonWithName:@"Amin"];
…
[person release]; // You create it, you release it

// ARC:
Person *person = [[Person newPersonWithName:@"Amin"];
…
Run Code Online (Sandbox Code Playgroud)

便利分配器

// MRR:
Person *person = [[Person personWithName:@"Amin"]; // Autoreleased
…

// ARC:
Person *person = [[Person personWithName:@"Amin"];
…
Run Code Online (Sandbox Code Playgroud)

如您所见,使用 ARC 创建对象的三种方式没有区别。所以里维埃拉是对的,当时他说这已经不重要了。但在幕后,最后一种方式是不同的,因为它将对象移动到 ARP。

这个方法的实现也是一样的:

实现一个新的分配器

// MRR
+ (Person*)newPersonWithName:(NSString*)name
{
    return [[self alloc] initWithName:name];
}

// ARC
+ (Person*)newPersonWithName:(NSString*)name
{
    return [[self alloc] initWithName:name];
}
Run Code Online (Sandbox Code Playgroud)

实现便利分配器

// MRR
+ (Person*)personWithName:(NSString*)name
{
    return [[[self alloc] initWithName:name] autorelease];
}

// ARC
+ (Person*)personWithName:(NSString*)name
{
    return [[self alloc] initWithName:name];
}
Run Code Online (Sandbox Code Playgroud)

同样,使用 ARC 时,这两种方法的实现是相同的。

->你不再需要任何这些规则了。ARC关心四个你。

尤其是您不再需要便利分配器,因为不再有任何不方便之处。(即使它们在运行时进行了优化,仍然存在最小的运行时损失。)我不再实现便利分配器,而是实现新的分配器。

但是ARC必须与MRR兼容。所以它记住了所有的规则。为了让你的代码对其他人可读,你也应该重复这个规则。但是,当然,现在便利分配器和新分配器的实现是按位相同的——其余的由 ARC 完成。


iRe*_*_85 0

我不知道 100% 传统命名方法的所有细节,因为每种方法都有不同的情况。不过我认为 Apple 文档中的这篇文章会对您有所帮助。https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/Conventions/Conventions.html