0

也许这是一个愚蠢的问题,但我真的很想弄清楚这个问题。

例如,我有以下设置:

// .h
@interface MyClass : NSObject
{
   NSView *myView;
}

// .m

@implementation MyClass

-(void)someMethod
{

   // WHAT IS THE DIFFERENCE BETWEEN THIS
   myView = [[NSView alloc] init];

   // AND THIS ?

   myView = [myView init]; // assuming that myView was allocated somewhere earlier in init method
}
4

3 回答 3

2

init方法倾向于假设您只向init每个对象发送一次。

init 再次发送到先前分配和初始化的myView将打破这个假设,导致内存泄漏和随后的奇怪行为。两者都来自您的第二init条消息,以myView创建同一对象之前已经设置的对象、添加观察者等。

这就是第二行的someMethod作用。

第一行创建了一个新视图,这是alloc/ initone-two 的影响。此视图与您输入的视图someMethod(如果有)是不同的对象,因此init作为其创建的一部分发送到该对象不是问题。

记住:对象不是变量。myView是变量的名称;当我们说“<code>myView”时,我们真正的意思是“myView持有的对象”。

(牢牢记住最后一段中的概念,从头开始重新阅读此答案可能是个好主意。)

于 2013-04-26T07:20:15.680 回答
1

该语句myView = [[NSView alloc] init];只是对以下内容的嵌套方法调用

NSView *myView =[NSView alloc]; //line 1
myView=[myView init];//line 2

如果您在单行或多行中执行此操作,则不会执行任何特定操作。

第 1 行:这里alloc为对象创建了一个新的内存位置。

第 2 行:将一个 Aninit发送到对象,以初始化该对象。

于 2013-04-26T05:30:46.190 回答
0

Objective-C 与许多其他面向对象的语言不同,它使对象创建成为一个明确的两阶段过程,分配初始化

如果您熟悉 Java、C# 和 C++ 等语言,那么对象创建的分配部分与初始化是不可分割的。因此,例如在 Java 中,您可以编写:

class Tree {

// constructor/initialiser
public Tree ()
{
   // whatever is needed to initialise a Tree
}

}

...
Tree myTree = new Tree(); // allocate and initalise a tree

Java 的new表达式为 a分配内存Tree,然后调用构造函数来正确设置该内存。

上述语言认识到分配和初始化只是真正单一操作的两个部分:对象创建。

在 Objective-C 中,上面的例子是:

@implementation Tree

// constructor/initialiser
(id) init ()
{
   // whatever is needed to initialise a Tree
}

@end

...
Tree *myTree = [[Tree alloc] init]; // allocate and initalise a tree

在这里,您理论上可以将分配和初始化分开,但不建议这样做。这样做的原因[Tree alloc]通常不会返回完全形成的Tree,它会分配一些内存并将其标记为 aTree但任何由 拥有的实例变量,或者未初始化Tree的超类-必须调用初始化。如果您将这两个操作分开,那么您可能会有不完整的对象,这些对象的行为将无法按预期进行。因此,尽管您可以将它们分开,但这样做非常不明智,以至于 Apple 的州文档:Treeinitinit

消息与同一行代码中的init消息耦合alloc

那就是Apple告诉你一个小谎言,以防止你犯下一个大错误。

Objective-C 也提供了单一的创建操作形式:

Tree *myTree = [Tree new]; // alloc + init

然而,与 Java不同的是,如果您编写一个带有参数的初始化程序,您不会自动获得一个带有new参数的版本 - 您需要自己编写(作为使用的类方法alloc和带有参数的初始化程序)。

高温高压

于 2013-04-26T09:46:14.953 回答