Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c 命名方法的简单规则,与ARC命名约定兼容_Objective C_Memory Leaks_Automatic Ref Counting_Naming Conventions_Class Method - Fatal编程技术网

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

Objective c 命名方法的简单规则,与ARC命名约定兼容,objective-c,memory-leaks,automatic-ref-counting,naming-conventions,class-method,Objective C,Memory Leaks,Automatic Ref Counting,Naming Conventions,Class Method,我很难理解ARC的命名约定。我一直用ARC编码,我想这就是原因 1.类方法 我应该为以下方法选择什么名称 关于内存管理,这两个名称之间有什么区别 姓名: + (MyObject *)newObjectFrom:(MyObject *)anObject withOptions:(NSDictionary*)options { MyObject * newObject = [anObject copy] ; [newObject modifyWi

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

1.类方法
  • 我应该为以下方法选择什么名称
  • 关于内存管理,这两个名称之间有什么区别
姓名:

+ (MyObject *)newObjectFrom:(MyObject *)anObject 
                withOptions:(NSDictionary*)options
{
    MyObject * newObject = [anObject copy] ;
    [newObject modifyWith:options] ;
    return newObject ;
}
- (MyObject *)newObjectwithOptions:(NSDictionary*)options
{
    MyObject * newObject = [self copy] ;
    [newObject modifyWith:options] ;
    return newObject ;
}
还是这个名字

+ (MyObject *)objectFrom:(MyObject *)anObject
             withOptions:(NSDictionary*)options
{
    MyObject * newObject = [anObject copy] ;
    [newObject modifyWith:options] ;
    return newObject ;
}
2.实例方法
  • 我应该为以下方法选择什么名称
  • 关于内存管理,这两个名称之间有什么区别
姓名:

+ (MyObject *)newObjectFrom:(MyObject *)anObject 
                withOptions:(NSDictionary*)options
{
    MyObject * newObject = [anObject copy] ;
    [newObject modifyWith:options] ;
    return newObject ;
}
- (MyObject *)newObjectwithOptions:(NSDictionary*)options
{
    MyObject * newObject = [self copy] ;
    [newObject modifyWith:options] ;
    return newObject ;
}
还是这个名字

- (MyObject *)objectwithOptions:(NSDictionary*)options
{
    MyObject * newObject = [self copy] ;
    [newObject modifyWith:options] ;
    return newObject ;
}
2.命名方法的简单规则 命名方法时有没有一个简单的基本规则可以遵循?

我说的“基本,简单”,是指

  • 类似于“
    strong
    当对象属于该类时”,“
    当该对象仅由该类引用,并且(因此)由另一类拥有时”的规则

  • (和/或)不涉及无
    ARC
    的内存管理的规则

  • (和/或)不使用“自动释放”、“释放”等词语的规则


按照惯例,我不知道命名方法的所有细节,因为每种方法都适用不同的情况。不过,我认为苹果文档中的这篇文章会对你有所帮助

首先,内存管理与您为方法或类选择的名称无关。换句话说,如果它编译了,并且您没有使用保留关键字或关键方法名称,那么您应该是好的。(请参阅编辑说明)

对于1,前面的
new
在Objective-C中非常少见,因此最好使用
objectFrom:

更好的方法是更精确地描述您正在创建的对象的类型。例如:

[NSArray arrayWithArray:]
[NSString stringWithFormat:]
或者在您创建副本的情况下,假设您正在创建“客户端”对象:

其中,实际上不需要使用

对于2,我会选择:

copyWithOptions:
当您或多或少地定制
[NSObject copy]
时。我还将只实现这个方法,并删除现在多余的1,因为更少的方法更清晰、更易于记录和维护

如果有疑问,只需搜索SDK文档,查看苹果如何命名类似的方法

编辑:


在第一段中,我的意思不是鼓励不好的命名实践,只是说它们不是内存管理问题的原因。然而,您应该尝试遵循其他答案中指出的命名约定,或者正如我所说的,“像苹果那样做”。

方法名称非常重要。ARC如何解释方法名称的官方文档可以在上一节的clang ARC文档中找到。

我在苹果世界的经验是,像您的示例那样的工厂方法通常包括按惯例“创建”。这在ARC中可能不那么重要了,但在过去,在方法或函数签名中“创建”是一种非常可靠的方法,可以确保您理解您是在获得结果对象的所有权(由于其上有一个release/free()),而不是假定为自动释放[NSArray array]、[uicolorWith..的实例类型等等,所以我仍然非常喜欢遵循这个惯例。

当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
做一个深入的分析,你会发现有时会有问题。(对象释放作为副作用。)但这是基本方法

这样做的好处是可以在本地(在复合语句中)处理retain-release对,并且很容易跟踪对象的所有权

规则2:但是当第一次创建对象时,这无法工作:消息的发送者总是持有它。否则它将被立即销毁(=在发送者有机会保留它之前)。因此有一个附加规则:

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

id object = [Class allocOrInitOrNewMethod];
…
[object release];
-retain
明确取得所有权时,
alloc–
init…
new…
隐式转移所有权

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

规则3:有时你需要一个自动释放池。 要使ARP的优势变得明显,请考虑以下代码:(它是无用的,只是为了演示问题

案例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
另一个问题:

案例2.1:

Person *person = [[Person alloc] initWithName:…]; // Ownership transfer, release person, when you are done
if (…)
{
   return; // break, continue, goto
}
…
[person release];
由于从未到达最后一行,因此对象从未释放

您可以使用自动释放方法修复该问题。只要控制流返回到运行循环,移动到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
案例2.2:

Person *person = [[[Person alloc] initWithName:…] autorelease]; // No ownership transfer, prsons belongs to the AR.
if (…)
{
   return; // break, continue, goto
}
…
// No release necessary.
因为人们不得不懒得键入这么长的消息链,所以方便性是有限的
Person *person = [personWithName:…]; // No ownership transfer, persons belongs to the AR.
if (…)
{
   return; // break, continue, goto
}
…
// No release necessary.
- (NSString*)name
{
   return [[_name retain] autorelease];
}
// MRR:
Person *person = [[Person alloc] initWithName:@"Amin"];
…
[person release]; // You create it, you release it

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

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

// ARC:
Person *person = [[Person personWithName:@"Amin"];
…
// MRR
+ (Person*)newPersonWithName:(NSString*)name
{
    return [[self alloc] initWithName:name];
}

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

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