iOS 的objective-c/cocoa 中存在哪些方法族?

Posted

技术标签:

【中文标题】iOS 的objective-c/cocoa 中存在哪些方法族?【英文标题】:What method families exist in objective-c/cocoa for iOS? 【发布时间】:2012-01-07 16:23:53 【问题描述】:

我是一位经验丰富的开发人员,不熟悉 ios 开发(尤其是 iPhone)。我正在进行的一个项目正在使用自动引用计数 (ARC)。

我正在对 ARC 进行一些研究,并偶然发现了这个文档:http://clang.llvm.org/docs/AutomaticReferenceCounting.html,并在标题为:“保留的返回值”的部分中指出,一个属性可用于指示调用者希望获得一个 + 1 保留计数。它还继续指出,如果 ARC 检测到该属性属于特定方法系列(它具体命名为:alloc、copy、init、mutableCopy 和 new),它将自动将属性添加到方法中

从进一步阅读来看,方法族似乎只是方法命名约定。我的理解是,如果方法名称以方法族开头,那么它就属于该方法族。比如

+(id) init
+(id) initWithName:(NSString*)name

都是 init 方法系列的一部分。

我的问题是:是否有正式的 iOS 开发方法族列表,如果有,它们是什么/我可以在哪里找到它?

下面是我上面提到的 llvm.org 部分:

第 3.2.2 节:保留的返回值状态:

返回可保留对象指针类型的函数或方法 可以被标记为返回一个保留值,表示 调用者希望获得 +1 保留计数的所有权。这是由 将 ns_returns_retained 属性添加到函数或方法 声明,像这样:

id foo(void) __attribute((ns_returns_retained)); - (id) foo __attribute((ns_returns_retained));该属性是函数或方法类型的一部分。

当从这样的函数或方法返回时,ARC 会保留该值 在返回语句的评估点,在离开所有 本地范围。

当接收到此类函数或方法的返回结果时,ARC 释放它包含的完整表达式末尾的值 内,受本地值的通常优化。

基本原理:这使被调用者的所有权直接转移正式化 给来电者。该模型最常见的情况是保留 从 init、alloc、new 和 copy 方法返回,但还有其他 框架中的案例。优化后通常没有 需要额外的保留和释放。

alloc、copy、init、mutableCopy 和 new 系列中的方法是 隐式标记属性((ns_returns_retained))。这可能是 通过显式标记方法来抑制 属性((ns_returns_not_retained))。

如果 Objective-C 消息发送到的方法是未定义的行为 发送静态解析的结果具有不同的保留语义 从它动态解析到的方法。这是未定义的行为 如果通过静态类型进行块或函数调用 其结果的不同保留语义 被调用的块或函数。

基本原理:与返回结果不匹配会导致过度保留或 过度释放,取决于方向。再次,关于规则 函数调用实际上只是现有 C/C++ 的一个应用 通过不兼容的函数类型调用函数的规则。

【问题讨论】:

我会注意到这些命名约定系列不是 iOS 特有的,而是 Objective-C ARC 特有的(其中 iOS 和 OS X 是目前唯一值得注意的用户(据我所知)) 【参考方案1】:

Section 5 of the same document 的标题是“方法族”。它列出了所有当前定义的族,即您在上面确定的族; allocnewcopymutableCopyinit。它还列出了成为该家庭成员的标准。大多数情况下,它仅基于方法名称,但也取决于返回类型。例如,copy 家族的成员必须返回一个对象;具有void 返回类型的复制方法将不被视为copy 方法系列的一部分。

【讨论】:

是的,该部分是我提出上述列表的地方。我意识到命名约定对objective-c/cocoa 很重要,但我有点惊讶编译器会受到命名约定的影响。我想我担心的一件事是由于我命名函数的方式,我可能会获得其他编译器优化。我不确定 ARC 文档中提供的列表是该语言的完整列表,还是仅适用于 ARC 的列表。 我不知道返回类型是家庭成员资格的一部分,谢谢。【参考方案2】:

我不知道我看过方法族的正式列表,但你的分析基本上是正确的。我相信唯一具有编译器强制语义的方法命名约定是您的帖子中提到的那些,即 alloc、init、copy(和 mutableCopy)和 new。即使在 ARC 之前/没有 ARC 之前,Xcode 中包含的 clang 静态分析器也使用这些命名约定来查找内存管理问题,它们也是 ARC 之前 Objective-C 程序员长期内存管理规则的基础。

也就是说,如果您使用以 init、copy、mutableCopy 或 new 开头的方法创建对象,则您“拥有”该对象并负责稍后释放它。由具有任何其他名称的方法创建或返回的对象归您(调用者)所有,如果您想保留对它们的引用,则必须保留它们。当您完成对象引用时,您所做的每个保留都必须由以后的版本平衡。最后,对对象调用 autorelease 会将其放入最里面的 autorelease 池中。池负责稍后释放对象,稍后是在当前范围之后的某个时间。因此,release 和 autorelease 都是放弃对对象的保留的有效方式。

现在,我提出的规则不应该(也不能)被 ARC 下的程序员遵循。但是,ARC 本质上是一个系统,在静态分析器的帮助下,编译器知道这些规则,并在编译时为您插入必要的内存管理调用。因此,如果您希望了解 ARC 在幕后所做的事情,了解这些规则是一个好的开始。

结果有点啰嗦,但重点是你命名的方法是我所知道的唯一在 Objective-C 中具有这种强制命名约定的方法,它源于上面列出的内存管理规则.可以肯定的是,Objective-C 中还有其他命名约定,但它们是标准样式约定,不是在任何地方强制执行的。

【讨论】:

【参考方案3】:

查看有关 Memory Management Rules 的官方 Apple Developer 文档。看来,您的列表很完整:“alloc”、“new”、“copy”或“mutableCopy”(只有 4 个关键字)。

【讨论】:

【参考方案4】:

我会包含一些 Cocoa 类提供的便利构造函数:

 - +stringWith*                        // Various ways to make NSString objects
 - +arrayWith*, +dictionaryWith*, etc. // Make collections
 - +dateWith*                          // Make NSDate objects
 - etc.                                // Many, many others

它们都返回一个新的、自动释放的类的实例——除了一些特殊情况,参见@Peter Hosey 的评论。

我不知道是否有任何正式规则,但模式是构造函数名称由没有NS 部分的类名组成(对于可变类也没有Mutable 部分)后跟With<Parameter Type>: 和一个或多个参数。该名称以小写字母开头(通常的嫌疑人除外,如URLWithString:。)

例如,以下行提供了一个带有单个元素的自动释放 NSArray 实例:

[NSArray arrayWithObject: @"Test"]

不知道编译器有没有什么特殊的规则可以识别这种类型的构造函数。

【讨论】:

它们不一定会返回自动发布的实例。它们可以返回现有实例,尤其是单例或实习对象(NSNumber,例如,某些整数值的实习对象,至少在 32 位上)。 对,忘记了。添加评论,谢谢。想到的另一个例子是stringWithString:,如果传递一个不可变的字符串,它只会返回相同的实例。

以上是关于iOS 的objective-c/cocoa 中存在哪些方法族?的主要内容,如果未能解决你的问题,请参考以下文章

Objective-C/Cocoa 中 Java 的 Thread.sleep() 等价物是啥?

Objective-C/Cocoa/XCode 新手:如何接收通知?

Objective-C / Cocoa:上传图像、工作内存和存储

如何在 Objective-C/Cocoa 中更改状态栏项目标题的颜色?

在代码中使用核心数据 - Objective-C/Cocoa

带有延迟 NSMenu 的 NSButton - Objective-C/Cocoa