使用子类阐明 init 方法

clarify init method using subclass

现在这个问题困扰了我很长一段时间,我真的需要有人为我澄清这个问题。

1) 什么是导致 init 方法 return 与您最初尝试通过调用分配的对象不同的对象的唯一标识符? ..遇到这种情况怎么办?

2) 当来自一个 class 的指定初始化器假设 class 有多个方法时,调用其父 class 中的指定初始化器,从而调用 NSObject 的 init 方法;调用父 class init 方法时到底发生了什么?该方法中的 "self" 是什么,以及从其根 class 编辑的 "self" return 是什么?

也许这会回答您的问题:

  • init 方法与其他任何方法一样,没有什么特别之处 本身 ;
  • 方法参数是分配了初始值的局部变量,该值是调用中给出的值;
  • self 是一个隐藏的方法参数,它的值与所有其他参数一样在调用中传递;
  • 该方法的结果隐式标记为ns_returns_retained attribute;最后
  • self 参数隐式标记为 ns_consumed attribute

提到的属性会影响 ARC 如何管理引用 returned (ns_returns_retained) 或传递给 (ns_consumes) 的方法。这些属性可以显式应用于任何方法。

属性 ns_returns_retained 隐式 应用于 alloccopyinit、[=25] 中的方法=],以及 new 个家庭;而 ns_consumes 隐式 应用于 init 方法的隐藏 self 参数。

ns_consumes 属性是 init 方法的唯一 "unusual" 特征。它告诉 ARC 被调用的方法拥有传递的对象引用的所有权,因此负责在需要时释放它。所以在 init 方法中找到的常见语句中,调用 superclass init 方法:

self = [super init];

存储在 self 中的当前引用与 调用者对该引用的所有权一起传递给被调用的方法 。当调用的结果被分配回 self 时,ARC 不需要放弃所有权(又名 "release")存储在那里的旧引用 - 所有权已经传递给被调用的方法 - 或取得所有权(又名"retain") 的新引用 - 因为被调用方将其所有权转移回调用方。

上面允许一个init方法return一个不同引用,而不是它被传递的引用,并释放它被传递的那个。此功能在用户 classes 中不常用,但在许多常见系统 classes 中使用,例如NSStringNSNumber,利用减少所需对象的数量。

以上听起来比实际上更复杂!如果您有具体问题,请按照@MichaelDautermann 在评论中的建议提出新的具体问题。

HTH

附录

作为对评论的回应,以下内容可能会有所帮助。 所有直接在 iPad 上键入的代码,预计会出现错误!

下面的方法是如何工作的?

- (NSString *) doSomething:(NSString *)aLocal
{
   aLocal = [super aLocal];
   return aLocal;
}

通话中:

NSString *someResult = [someObjectRef doSomething:someLocalVariable];

其中 someObjectRef 是一个变量,其中包含对声明上述方法的对象的引用,someLocalVariable 包含对字符串的引用。

大纲是:

  • 创建了一个新的方法调用及其局部变量aLocal
  • 存储在调用者someLocalVariable中的引用被复制(它是而不是它引用的对象)并存储在aLocal
  • 方法的语句被执行
  • 第一条语句是调用superclass中实现的同一个方法,aLocal中引用的值传递给这个方法,引用return ed 被调用存储到 aLocal - 替换以前存储在那里的引用。
  • 第二条语句return将存储在aLocal中的引用值作为方法结果,并将该引用存储到调用者的someLocalVariable.

None 应该是令人惊讶的,并且引用 return 可能不是传入的引用(它 可能 是,我们没有想知道继承的 doSomething 方法做了什么,它可能只是 return 它传递的内容)。

现在您只需要了解 self 是一个 隐式 传递的参数。这意味着上述方法有效声明为:

- (NSString *) doSomething:(NSString *)aLocal selfRef:(instancetype)self

和 Objective-C 自动提供作为 selfRef 传递的引用并存储到方法的局部变量 self.

最终将 doSomething 的名称更改为 initAndDoSomething 更改了 ARC 自动处理作为 self 传递的引用的方式以及 returned 以确保不会留下不需要的对象 - 这是通过隐式添加原始答案中提到的属性来完成的。

就是这样,init 方法是只是 方法。不要认为他们很特别,这会夸大他们的自我;-)

HTH