I have difficulties understanding naming conventions of ARC. I have always coded with ARC, and I guess this is the reason.
我很难理解ARC的命名习惯。我一直用ARC编码,我想这就是原因。
1. Class methods
- What name should I choose for the following method?
- 我应该为以下方法选择什么名称?
- What are the differences, concerning memory management, between theses two names?
- 这两个名字在内存管理方面有什么不同?
This name:
这个名字:
+ (MyObject *)newObjectFrom:(MyObject *)anObject
withOptions:(NSDictionary*)options
{
MyObject * newObject = [anObject copy] ;
[newObject modifyWith:options] ;
return newObject ;
}
or this name ?
还是这个名字?
+ (MyObject *)objectFrom:(MyObject *)anObject
withOptions:(NSDictionary*)options
{
MyObject * newObject = [anObject copy] ;
[newObject modifyWith:options] ;
return newObject ;
}
2. Instance methods
- What name should I choose for the following method?
- 我应该为以下方法选择什么名称?
- What are the differences, concerning memory management, between theses two names?
- 这两个名字在内存管理方面有什么不同?
This name:
这个名字:
- (MyObject *)newObjectwithOptions:(NSDictionary*)options
{
MyObject * newObject = [self copy] ;
[newObject modifyWith:options] ;
return newObject ;
}
or this name?
还是这个名字?
- (MyObject *)objectwithOptions:(NSDictionary*)options
{
MyObject * newObject = [self copy] ;
[newObject modifyWith:options] ;
return newObject ;
}
2. Simple rules for naming methods
Is there a basic, simple rule to follow when naming methods?
命名方法时是否遵循一个基本的、简单的规则?
By "basic, simple", I mean
我的意思是“基本的,简单的”
-
a rule similar to "
strong
when the object belongs to the class", "weak
when the object is just referred to by this class, and (thus) owned by another class";类似于“对象属于类时为强”的规则,“对象只是由类引用时为弱,并且(因此)由另一个类拥有”的规则;
-
(and/or) a rule that does not refer to the memory management without
ARC
;(和/或)不涉及无弧的内存管理的规则;
-
(and/or) a rule that does not use words such as "autorelease", "release".
(和/或)不使用“自动发送”、“释放”等词的规则。
7 个解决方案
#1
5
Method names are important. The official documentation of how ARC interprets method names can be found in the clang ARC documentation in the section on method families.
方法名称是很重要的。关于ARC如何解释方法名称的正式文档可以在“方法族”一节的clang ARC文档中找到。
#2
4
When Rivera said that method names are not important, he probably followed his experience: It always works. And this is correct. And you are correct that you probably do not understand the role of method names because you has always used ARC. So what is the big deal with it?
当Rivera说方法名不重要时,他可能会遵循他的经验:它总是有效的。这是正确的。您可能不理解方法名的作用,这是正确的,因为您一直使用圆弧。这有什么大不了的?
I added a synopsis to show the problem with MRR at the end of this answer. As you can see there, you do not have to care about naming rules using ARC the way you had to with MRR.
我在这个答案的最后添加了一个大纲来显示MRR的问题。正如您所看到的那样,您不必关心使用与MRR相同的方式使用ARC的命名规则。
To give you a more detailed explanation, you have to understand what happens using MRR:
为了给你一个更详细的解释,你必须了解使用MRR会发生什么:
Prior to ARC one had to do memory management manually. Doing so he had to know, what kind of ownership a return value has. To make a long story short, one had to know, whether he has to release a returned object:
在使用ARC之前,必须手动进行内存管理。这样做,他必须知道回报价值的所有权是什么。长话短说,一个人必须知道,他是否必须释放一个归还的物品:
Rule 1: You do not own an object returned by a method automatically. If you want to hold it, retain it and release it, when you are done with it.
规则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
Doing a deep analysis you can see that there are sometimes problems. (Object deallocation as a side effect.) But this was the basic approach.
做一个深入的分析,你会发现有时会有问题。(作为副作用的对象释放)但这是最基本的方法。
The advantage of that was that a retain-release pair could be handled locally (inside a compound statement) and it was easy to follow the ownership of an object.
这样做的好处是可以在本地(在复合语句中)处理保留-释放对,并且很容易跟踪对象的所有权。
Rule 2: But when an object was created the first time this could not work: The sender of the message has always to hold it. Otherwise it would be destroyed immediately (= before the sender has the chance to retain it.) So there was a additional rule:
规则2:但是当一个对象第一次被创建时,它就不能工作了:消息的发送者总是持有它。否则,它将被立即销毁(=在发送者有机会保留它之前)。所以有一个附加的规则:
If the name of a class method that returns an object starts with alloc, init, or new you have to handle the returned object as you did a retain on it. Or in one word: Ownership transfer:
如果返回对象的类方法的名称以alloc、init或new开头,则必须像处理retain一样处理返回的对象。或者用一个词来说:所有权转移:
id object = [Class allocOrInitOrNewMethod];
…
[object release];
As -retain
took the ownership explicitly, alloc–
, init…
, new…
transferred it implicitly.
当-retain明确地获取所有权时,alloc -, init…,new…
All other methods behaves like rule 1.
所有其他方法都遵循规则1。
Rule 3: Sometime you need an autorelease pool. To make the advantage of ARPs visible think of this code: (It is useless, just to demonstrate the problem
规则3:有时候你需要一个自动上传池。要使ARPs的优势可见,请考虑以下代码:(它没有用,只是为了演示问题
Case 1.1:
例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
Another problem:
另一个问题:
Case 2.1:
例2.1:
Person *person = [[Person alloc] initWithName:…]; // Ownership transfer, release person, when you are done
if (…)
{
return; // break, continue, goto
}
…
[person release];
Because the last line is never reached, the object is never released.
因为没有到达最后一行,所以不会释放对象。
You can repair that with autoreleasing methods. An object moved to the ARP lives as long as the control flow returns to the run loop. So it lives through every method, through method return and so on. To do it explicitly:
您可以使用自动发送方法修复它。只要控制流返回到运行循环,移动到ARP的对象就可以存活。所以它通过各种方法存在,通过方法返回等等。做明确:
Case 1.2:
例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
Case 2.2:
例2.2:
Person *person = [[[Person alloc] initWithName:…] autorelease]; // No ownership transfer, prsons belongs to the AR.
if (…)
{
return; // break, continue, goto
}
…
// No release necessary.
Because one has to be too lazy to type such a long message chain, convenience allocators has been invented to do this for you:
因为一个人太懒了,不能输入这么长的信息链,所以发明了方便的分配器来为你做这个:
+ (Person*)personWithName:(NSString*)name
{
return [[[self alloc] initWithName:name] autorelease];
}
With the result:
结果:
Case 2.3:
例2.3:
Person *person = [personWithName:…]; // No ownership transfer, persons belongs to the AR.
if (…)
{
return; // break, continue, goto
}
…
// No release necessary.
And you can do the same with getters:
你也可以用getters来做同样的事情:
- (NSString*)name
{
return [[_name retain] autorelease];
}
So we at the end of the day we have simple rules:
所以在一天结束的时候我们有一些简单的规则:
Rule 1: If you want to keep a returned object in memory retain it – and release it, when you do not need it any more.
规则1:如果您想在内存中保留返回的对象,请保留它——并在不再需要它时释放它。
Rule 2: If the class method's name starts with alloc, new, or init, think of it as an implicit retain
(and therefore release it, when you are done with the object.)
规则2:如果类方法的名称以alloc、new或init开始,请将其视为隐式保留(因此,当您使用对象完成时,释放它)。
Rule 3: Use -autorelease
to delay the deallocation of returned objects for convenience.
规则3:为了方便,使用-autorelease延迟返回对象的释放。
Synopsis:
剧情简介:
Alloc-init creation
init创造
// MRR:
Person *person = [[Person alloc] initWithName:@"Amin"];
…
[person release]; // You create it, you release it
// ARC:
Person *person = [[Person alloc] initWithName:@"Amin"];
…
New creator
新的创造者
// MRR:
Person *person = [[Person newPersonWithName:@"Amin"];
…
[person release]; // You create it, you release it
// ARC:
Person *person = [[Person newPersonWithName:@"Amin"];
…
Convenience allocator
方便分配器
// MRR:
Person *person = [[Person personWithName:@"Amin"]; // Autoreleased
…
// ARC:
Person *person = [[Person personWithName:@"Amin"];
…
As you can see, there is no difference for the three ways of object creation using ARC. So Riviera is right, when he said that this is not important any more. But under the hood the last way is different, because it moves the object to the ARP.
如您所见,使用ARC创建对象的三种方式没有区别。所以里维埃拉说得对,他说这不再重要了。但在引擎盖下面,最后一种方式是不同的,因为它将对象移动到ARP。
It is the same with the implementation of this methods:
这些方法的实施情况是一样的:
Implementing a new allocator
实现一个新的分配器
// MRR
+ (Person*)newPersonWithName:(NSString*)name
{
return [[self alloc] initWithName:name];
}
// ARC
+ (Person*)newPersonWithName:(NSString*)name
{
return [[self alloc] initWithName:name];
}
Implementing a convenience allocator
实现方便分配器
// MRR
+ (Person*)personWithName:(NSString*)name
{
return [[[self alloc] initWithName:name] autorelease];
}
// ARC
+ (Person*)personWithName:(NSString*)name
{
return [[self alloc] initWithName:name];
}
Again the implementation for both methods is identical using ARC.
使用ARC,这两种方法的实现都是相同的。
-> You do not need it any of this rules any more. ARC cares four you.
->你不再需要这些规则了。电弧管四个你。
Especially you do not need convenience allocators any more, because there is nothing inconvenient any more. (And even they are optimized at run time, there is still a minimal runtime penalty.) I do not implement convenience allocators any more, but new allocators.
特别是您不再需要方便的分配器,因为不再有任何不便。(即使它们在运行时进行了优化,运行时的损失仍然很小。)我不再执行方便分配器,而是新的分配器。
But ARC has to be compatible with MRR. So it remembers all that rules. To make your code readable for others you should repeat this rules, too. But, of course, now the implementation of a convenience allocator and a new allocator is bitwise identical – the rest is done by ARC.
但是ARC必须与MRR兼容。所以它记住了所有的规则。为了使您的代码对其他人可读,您也应该重复这些规则。但是,当然,现在方便的分配器和新的分配器的实现是位相同的——其余的是由ARC完成的。
#3
1
Method naming conventions are important when converting the code from MRC to ARC, and when interoperating with MRC code from ARC Code.
Apple guide says that with "ARC code only" the naming conventions are "less important", but this is not 100% true.
方法命名约定在将代码从MRC转换为ARC以及与来自ARC代码的MRC代码互操作时非常重要。苹果指南说,使用“仅使用ARC代码”,命名约定“不那么重要”,但这并不是100%正确的。
For example (and this is only one example, I think that there are many other), look at this project
例如(这只是一个例子,我认为还有很多其他的例子),看看这个项目
I swizzled release-autorelease calls to log it, and you can see the difference:
我滑动了release-autorelease调用来记录它,你可以看到区别:
when a method begins with a special naming (for example "new"), ARC returns an object with a retain count of +1, that is balanced by release calls.
When a difference name is used, ARC returns an AUTORELEASED object. (look at the NSLog calls)
当一个方法以一个特殊的命名(例如“new”)开始时,ARC返回一个保留计数为+1的对象,该对象由发布调用来平衡。当使用不同的名称时,ARC将返回一个自动上传的对象。(看看NSLog调用)
This can be a big difference in code that alloc a great number of objects in a loop. In this case, the programmer should create an autorelease pool.
这可能是代码的一个很大的不同,因为循环中分配了大量的对象。在这种情况下,程序员应该创建一个自动上传池。
So, it's not true that the naming conventions are less important when using ARC-only code.
因此,在使用只使用arconly代码时,命名约定并不那么重要。
#4
0
I don't know all of the details on naming methods 100% conventionally because there are different situations that apply to each. however I think this article in the Apple docs will help you. https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/Conventions/Conventions.html
我不完全了解命名方法的所有细节,因为每种方法都适用不同的情况。然而,我认为在苹果文档中的这篇文章将对您有所帮助。https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/Conventions/Conventions.html
#5
0
My experience in the apple world is that factory methods like your examples would usually include 'create' by convention. This is probably less important now with ARC but in the old days 'create' in a method or function signature was a pretty sure fire way to be sure you understood you were taking ownership of the resulting object (owing a release/free() on it) rather than an instance type which you would assume to autorelease [NSArray array] , [UIColor colorWith....] etc, so I still definitely like to follow this convention.
我在苹果世界的经验是,像您的示例这样的工厂方法通常会按照惯例包括“create”。这可能是不太重要的现在与弧但以前创建的方法或函数签名是一个很确定火灾的方法确保你理解你正在生成的对象的所有权(由于发布/免费()),而不是一个实例类型,你将承担autorelease[NSArray数组],[用户界面颜色colorWith ....等等,所以我还是很喜欢遵循这个惯例。
#6
0
-
ARC gave semantics to what used to be a naming convention for tracking reference counting responsibilities. So now the compiler uses the same naming patterns to determine whether a method returns a retained object, etc. See the link in @JodyHagens' answer and continue reading with http://clang.llvm.org/docs/AutomaticReferenceCounting.html#semantics-of-method-families
ARC给出了用于跟踪引用计数责任的命名约定的语义。因此,现在编译器使用相同的命名模式来确定一个方法是否返回一个保留的对象,等等。
Methods in the
alloc
,copy
,mutableCopy
, andnew
families — that is, methods in all the currently-defined families exceptinit
— implicitly return a retained object as if they were annotated with thens_returns_retained
attribute. This can be overridden by annotating the method with either of thens_returns_autoreleased
orns_returns_not_retained
attributes.方法在alloc、copy、mutableCopy和新家庭中——也就是说,所有当前定义的家庭中的方法,除了init -隐式地返回一个保留对象,就像使用ns_returns_保留属性进行注释一样。可以通过使用ns_returns_autorele或ns_returns_not_保留属性对方法进行注释来重写此操作。
The "
new
family" is the message selectors that start with "new" followed by an upper case letter. So there are memory management differences betweennewObjectFrom:withOptions:
andobjectFrom:withOptions:
, but you can use an annotation to override that (don't go there), and the compiler should complain if you get it wrong.“new family”是以“new”开头,后面跟着大写字母的消息选择器。因此,newObjectFrom:withOptions:和objectFrom:withOptions:之间存在内存管理上的差异,但是您可以使用注释来覆盖它(不要到那里去),如果您做错了,编译器应该会抱怨。
(All methods that implement a given message selector had better provide the same reference counting semantics.)
(实现给定消息选择器的所有方法最好提供相同的引用计数语义。)
-
In addition to Apple's article on Conventions that @iRebel_85 points out, Apple has an extensive set of naming guidelines.
除了@iRebel_85指出的苹果关于惯例的文章之外,苹果还有一套广泛的命名指南。
- Google's style guide adds a few more naming guidelines.
- 谷歌的风格指南增加了一些命名指南。
These guidelines are well thought out and useful for making code easier to understand and collaborate on.
这些指导方针经过深思熟虑,对于使代码更易于理解和协作非常有用。
#7
0
First, memory management has nothing to do with the names you choose for your methods or classes. In other words if it compiles and you're not using reserved keywords or critical method names you should be good. (Please refer to Edit note)
首先,内存管理与为方法或类选择的名称无关。换句话说,如果它编译了,而您没有使用保留的关键字或关键的方法名,那么您应该做得很好。(请参阅编辑注释)
As for 1, preceding new
is very uncommon in Objective-C, so it's better to use objectFrom:
instead.
对于1,在Objective-C中,前面的new非常少见,所以最好使用objectFrom:来代替。
Even better would be to be more precise about the kind of object you're creating. For example:
更好的做法是更精确地描述您正在创建的对象。例如:
[NSArray arrayWithArray:]
[NSString stringWithFormat:]
Or in your case as you create a copy, and supposing you're creating "Client" objects:
或者在你创建一个副本时,假设你正在创建“客户”对象:
[Client clientWithClient:options:]
Where with
is not really needed.
这里不需要with。
For 2 I would choose:
对于2,我会选择:
copyWithOptions:
As you're more or less customizing [NSObject copy]
. I would also implement only this method and delete the now redundant 1 as less methods is clearer, easier to document, and easier to maintain!
随着您或多或少地自定义[NSObject拷贝]。我还将只实现这个方法,并删除现在的冗余1,因为更少的方法更清晰,更容易文档化,并且更容易维护!
In case of doubt just search the SDK documentation to see how similar methods were named by Apple.
如果有疑问,只需搜索SDK文档,看看类似的方法是如何被苹果命名的。
Edit:
编辑:
In the first paragraph I don't mean to encourage bad naming practices, just to say that they are not the reason for your memory management concerns. Yet you should try to follow the naming conventions pointed in the other answers, or as I said, "do as Apple does".
在第一段中,我并不是要鼓励糟糕的命名实践,只是说它们不是您的内存管理关注的原因。然而,你应该遵循其他答案中提到的命名惯例,或者像我说的那样,“像苹果那样做”。
#1
5
Method names are important. The official documentation of how ARC interprets method names can be found in the clang ARC documentation in the section on method families.
方法名称是很重要的。关于ARC如何解释方法名称的正式文档可以在“方法族”一节的clang ARC文档中找到。
#2
4
When Rivera said that method names are not important, he probably followed his experience: It always works. And this is correct. And you are correct that you probably do not understand the role of method names because you has always used ARC. So what is the big deal with it?
当Rivera说方法名不重要时,他可能会遵循他的经验:它总是有效的。这是正确的。您可能不理解方法名的作用,这是正确的,因为您一直使用圆弧。这有什么大不了的?
I added a synopsis to show the problem with MRR at the end of this answer. As you can see there, you do not have to care about naming rules using ARC the way you had to with MRR.
我在这个答案的最后添加了一个大纲来显示MRR的问题。正如您所看到的那样,您不必关心使用与MRR相同的方式使用ARC的命名规则。
To give you a more detailed explanation, you have to understand what happens using MRR:
为了给你一个更详细的解释,你必须了解使用MRR会发生什么:
Prior to ARC one had to do memory management manually. Doing so he had to know, what kind of ownership a return value has. To make a long story short, one had to know, whether he has to release a returned object:
在使用ARC之前,必须手动进行内存管理。这样做,他必须知道回报价值的所有权是什么。长话短说,一个人必须知道,他是否必须释放一个归还的物品:
Rule 1: You do not own an object returned by a method automatically. If you want to hold it, retain it and release it, when you are done with it.
规则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
Doing a deep analysis you can see that there are sometimes problems. (Object deallocation as a side effect.) But this was the basic approach.
做一个深入的分析,你会发现有时会有问题。(作为副作用的对象释放)但这是最基本的方法。
The advantage of that was that a retain-release pair could be handled locally (inside a compound statement) and it was easy to follow the ownership of an object.
这样做的好处是可以在本地(在复合语句中)处理保留-释放对,并且很容易跟踪对象的所有权。
Rule 2: But when an object was created the first time this could not work: The sender of the message has always to hold it. Otherwise it would be destroyed immediately (= before the sender has the chance to retain it.) So there was a additional rule:
规则2:但是当一个对象第一次被创建时,它就不能工作了:消息的发送者总是持有它。否则,它将被立即销毁(=在发送者有机会保留它之前)。所以有一个附加的规则:
If the name of a class method that returns an object starts with alloc, init, or new you have to handle the returned object as you did a retain on it. Or in one word: Ownership transfer:
如果返回对象的类方法的名称以alloc、init或new开头,则必须像处理retain一样处理返回的对象。或者用一个词来说:所有权转移:
id object = [Class allocOrInitOrNewMethod];
…
[object release];
As -retain
took the ownership explicitly, alloc–
, init…
, new…
transferred it implicitly.
当-retain明确地获取所有权时,alloc -, init…,new…
All other methods behaves like rule 1.
所有其他方法都遵循规则1。
Rule 3: Sometime you need an autorelease pool. To make the advantage of ARPs visible think of this code: (It is useless, just to demonstrate the problem
规则3:有时候你需要一个自动上传池。要使ARPs的优势可见,请考虑以下代码:(它没有用,只是为了演示问题
Case 1.1:
例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
Another problem:
另一个问题:
Case 2.1:
例2.1:
Person *person = [[Person alloc] initWithName:…]; // Ownership transfer, release person, when you are done
if (…)
{
return; // break, continue, goto
}
…
[person release];
Because the last line is never reached, the object is never released.
因为没有到达最后一行,所以不会释放对象。
You can repair that with autoreleasing methods. An object moved to the ARP lives as long as the control flow returns to the run loop. So it lives through every method, through method return and so on. To do it explicitly:
您可以使用自动发送方法修复它。只要控制流返回到运行循环,移动到ARP的对象就可以存活。所以它通过各种方法存在,通过方法返回等等。做明确:
Case 1.2:
例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
Case 2.2:
例2.2:
Person *person = [[[Person alloc] initWithName:…] autorelease]; // No ownership transfer, prsons belongs to the AR.
if (…)
{
return; // break, continue, goto
}
…
// No release necessary.
Because one has to be too lazy to type such a long message chain, convenience allocators has been invented to do this for you:
因为一个人太懒了,不能输入这么长的信息链,所以发明了方便的分配器来为你做这个:
+ (Person*)personWithName:(NSString*)name
{
return [[[self alloc] initWithName:name] autorelease];
}
With the result:
结果:
Case 2.3:
例2.3:
Person *person = [personWithName:…]; // No ownership transfer, persons belongs to the AR.
if (…)
{
return; // break, continue, goto
}
…
// No release necessary.
And you can do the same with getters:
你也可以用getters来做同样的事情:
- (NSString*)name
{
return [[_name retain] autorelease];
}
So we at the end of the day we have simple rules:
所以在一天结束的时候我们有一些简单的规则:
Rule 1: If you want to keep a returned object in memory retain it – and release it, when you do not need it any more.
规则1:如果您想在内存中保留返回的对象,请保留它——并在不再需要它时释放它。
Rule 2: If the class method's name starts with alloc, new, or init, think of it as an implicit retain
(and therefore release it, when you are done with the object.)
规则2:如果类方法的名称以alloc、new或init开始,请将其视为隐式保留(因此,当您使用对象完成时,释放它)。
Rule 3: Use -autorelease
to delay the deallocation of returned objects for convenience.
规则3:为了方便,使用-autorelease延迟返回对象的释放。
Synopsis:
剧情简介:
Alloc-init creation
init创造
// MRR:
Person *person = [[Person alloc] initWithName:@"Amin"];
…
[person release]; // You create it, you release it
// ARC:
Person *person = [[Person alloc] initWithName:@"Amin"];
…
New creator
新的创造者
// MRR:
Person *person = [[Person newPersonWithName:@"Amin"];
…
[person release]; // You create it, you release it
// ARC:
Person *person = [[Person newPersonWithName:@"Amin"];
…
Convenience allocator
方便分配器
// MRR:
Person *person = [[Person personWithName:@"Amin"]; // Autoreleased
…
// ARC:
Person *person = [[Person personWithName:@"Amin"];
…
As you can see, there is no difference for the three ways of object creation using ARC. So Riviera is right, when he said that this is not important any more. But under the hood the last way is different, because it moves the object to the ARP.
如您所见,使用ARC创建对象的三种方式没有区别。所以里维埃拉说得对,他说这不再重要了。但在引擎盖下面,最后一种方式是不同的,因为它将对象移动到ARP。
It is the same with the implementation of this methods:
这些方法的实施情况是一样的:
Implementing a new allocator
实现一个新的分配器
// MRR
+ (Person*)newPersonWithName:(NSString*)name
{
return [[self alloc] initWithName:name];
}
// ARC
+ (Person*)newPersonWithName:(NSString*)name
{
return [[self alloc] initWithName:name];
}
Implementing a convenience allocator
实现方便分配器
// MRR
+ (Person*)personWithName:(NSString*)name
{
return [[[self alloc] initWithName:name] autorelease];
}
// ARC
+ (Person*)personWithName:(NSString*)name
{
return [[self alloc] initWithName:name];
}
Again the implementation for both methods is identical using ARC.
使用ARC,这两种方法的实现都是相同的。
-> You do not need it any of this rules any more. ARC cares four you.
->你不再需要这些规则了。电弧管四个你。
Especially you do not need convenience allocators any more, because there is nothing inconvenient any more. (And even they are optimized at run time, there is still a minimal runtime penalty.) I do not implement convenience allocators any more, but new allocators.
特别是您不再需要方便的分配器,因为不再有任何不便。(即使它们在运行时进行了优化,运行时的损失仍然很小。)我不再执行方便分配器,而是新的分配器。
But ARC has to be compatible with MRR. So it remembers all that rules. To make your code readable for others you should repeat this rules, too. But, of course, now the implementation of a convenience allocator and a new allocator is bitwise identical – the rest is done by ARC.
但是ARC必须与MRR兼容。所以它记住了所有的规则。为了使您的代码对其他人可读,您也应该重复这些规则。但是,当然,现在方便的分配器和新的分配器的实现是位相同的——其余的是由ARC完成的。
#3
1
Method naming conventions are important when converting the code from MRC to ARC, and when interoperating with MRC code from ARC Code.
Apple guide says that with "ARC code only" the naming conventions are "less important", but this is not 100% true.
方法命名约定在将代码从MRC转换为ARC以及与来自ARC代码的MRC代码互操作时非常重要。苹果指南说,使用“仅使用ARC代码”,命名约定“不那么重要”,但这并不是100%正确的。
For example (and this is only one example, I think that there are many other), look at this project
例如(这只是一个例子,我认为还有很多其他的例子),看看这个项目
I swizzled release-autorelease calls to log it, and you can see the difference:
我滑动了release-autorelease调用来记录它,你可以看到区别:
when a method begins with a special naming (for example "new"), ARC returns an object with a retain count of +1, that is balanced by release calls.
When a difference name is used, ARC returns an AUTORELEASED object. (look at the NSLog calls)
当一个方法以一个特殊的命名(例如“new”)开始时,ARC返回一个保留计数为+1的对象,该对象由发布调用来平衡。当使用不同的名称时,ARC将返回一个自动上传的对象。(看看NSLog调用)
This can be a big difference in code that alloc a great number of objects in a loop. In this case, the programmer should create an autorelease pool.
这可能是代码的一个很大的不同,因为循环中分配了大量的对象。在这种情况下,程序员应该创建一个自动上传池。
So, it's not true that the naming conventions are less important when using ARC-only code.
因此,在使用只使用arconly代码时,命名约定并不那么重要。
#4
0
I don't know all of the details on naming methods 100% conventionally because there are different situations that apply to each. however I think this article in the Apple docs will help you. https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/Conventions/Conventions.html
我不完全了解命名方法的所有细节,因为每种方法都适用不同的情况。然而,我认为在苹果文档中的这篇文章将对您有所帮助。https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/Conventions/Conventions.html
#5
0
My experience in the apple world is that factory methods like your examples would usually include 'create' by convention. This is probably less important now with ARC but in the old days 'create' in a method or function signature was a pretty sure fire way to be sure you understood you were taking ownership of the resulting object (owing a release/free() on it) rather than an instance type which you would assume to autorelease [NSArray array] , [UIColor colorWith....] etc, so I still definitely like to follow this convention.
我在苹果世界的经验是,像您的示例这样的工厂方法通常会按照惯例包括“create”。这可能是不太重要的现在与弧但以前创建的方法或函数签名是一个很确定火灾的方法确保你理解你正在生成的对象的所有权(由于发布/免费()),而不是一个实例类型,你将承担autorelease[NSArray数组],[用户界面颜色colorWith ....等等,所以我还是很喜欢遵循这个惯例。
#6
0
-
ARC gave semantics to what used to be a naming convention for tracking reference counting responsibilities. So now the compiler uses the same naming patterns to determine whether a method returns a retained object, etc. See the link in @JodyHagens' answer and continue reading with http://clang.llvm.org/docs/AutomaticReferenceCounting.html#semantics-of-method-families
ARC给出了用于跟踪引用计数责任的命名约定的语义。因此,现在编译器使用相同的命名模式来确定一个方法是否返回一个保留的对象,等等。
Methods in the
alloc
,copy
,mutableCopy
, andnew
families — that is, methods in all the currently-defined families exceptinit
— implicitly return a retained object as if they were annotated with thens_returns_retained
attribute. This can be overridden by annotating the method with either of thens_returns_autoreleased
orns_returns_not_retained
attributes.方法在alloc、copy、mutableCopy和新家庭中——也就是说,所有当前定义的家庭中的方法,除了init -隐式地返回一个保留对象,就像使用ns_returns_保留属性进行注释一样。可以通过使用ns_returns_autorele或ns_returns_not_保留属性对方法进行注释来重写此操作。
The "
new
family" is the message selectors that start with "new" followed by an upper case letter. So there are memory management differences betweennewObjectFrom:withOptions:
andobjectFrom:withOptions:
, but you can use an annotation to override that (don't go there), and the compiler should complain if you get it wrong.“new family”是以“new”开头,后面跟着大写字母的消息选择器。因此,newObjectFrom:withOptions:和objectFrom:withOptions:之间存在内存管理上的差异,但是您可以使用注释来覆盖它(不要到那里去),如果您做错了,编译器应该会抱怨。
(All methods that implement a given message selector had better provide the same reference counting semantics.)
(实现给定消息选择器的所有方法最好提供相同的引用计数语义。)
-
In addition to Apple's article on Conventions that @iRebel_85 points out, Apple has an extensive set of naming guidelines.
除了@iRebel_85指出的苹果关于惯例的文章之外,苹果还有一套广泛的命名指南。
- Google's style guide adds a few more naming guidelines.
- 谷歌的风格指南增加了一些命名指南。
These guidelines are well thought out and useful for making code easier to understand and collaborate on.
这些指导方针经过深思熟虑,对于使代码更易于理解和协作非常有用。
#7
0
First, memory management has nothing to do with the names you choose for your methods or classes. In other words if it compiles and you're not using reserved keywords or critical method names you should be good. (Please refer to Edit note)
首先,内存管理与为方法或类选择的名称无关。换句话说,如果它编译了,而您没有使用保留的关键字或关键的方法名,那么您应该做得很好。(请参阅编辑注释)
As for 1, preceding new
is very uncommon in Objective-C, so it's better to use objectFrom:
instead.
对于1,在Objective-C中,前面的new非常少见,所以最好使用objectFrom:来代替。
Even better would be to be more precise about the kind of object you're creating. For example:
更好的做法是更精确地描述您正在创建的对象。例如:
[NSArray arrayWithArray:]
[NSString stringWithFormat:]
Or in your case as you create a copy, and supposing you're creating "Client" objects:
或者在你创建一个副本时,假设你正在创建“客户”对象:
[Client clientWithClient:options:]
Where with
is not really needed.
这里不需要with。
For 2 I would choose:
对于2,我会选择:
copyWithOptions:
As you're more or less customizing [NSObject copy]
. I would also implement only this method and delete the now redundant 1 as less methods is clearer, easier to document, and easier to maintain!
随着您或多或少地自定义[NSObject拷贝]。我还将只实现这个方法,并删除现在的冗余1,因为更少的方法更清晰,更容易文档化,并且更容易维护!
In case of doubt just search the SDK documentation to see how similar methods were named by Apple.
如果有疑问,只需搜索SDK文档,看看类似的方法是如何被苹果命名的。
Edit:
编辑:
In the first paragraph I don't mean to encourage bad naming practices, just to say that they are not the reason for your memory management concerns. Yet you should try to follow the naming conventions pointed in the other answers, or as I said, "do as Apple does".
在第一段中,我并不是要鼓励糟糕的命名实践,只是说它们不是您的内存管理关注的原因。然而,你应该遵循其他答案中提到的命名惯例,或者像我说的那样,“像苹果那样做”。