Cocoa中的Alloc和init

时间:2013-04-26 05:11:22

标签: macos cocoa init alloc

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

例如,我有以下设置:

// .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
}

3 个答案:

答案 0 :(得分:2)

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

再次发送init 到先前分配和初始化的myView将打破此假设,导致内存泄漏以及可能的后续奇怪行为。两者都是由于您的第二条init消息导致myView创建对象,添加了观察者等,这些消息是之前已经设置过的。

这就是someMethod中的第二行。

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

记住:对象不是变量。 myView是变量的名称;当我们说“myView”时,我们的意思是“myView拥有的对象”。

(最好从最后一段重新阅读这个答案,并牢记最后一段中的概念。)

答案 1 :(得分:1)

此语句myView = [[NSView alloc] init];只是对以下

的嵌套方法调用
NSView *myView =[NSView alloc]; //line 1
myView=[myView init];//line 2

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

第1行:此处新的内存位置为alloc对象。

第2行:向对象发送init以初始化对象。

答案 2 :(得分: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表达式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,它会分配一些内存并将其标记为TreeTree拥有的任何实例变量}或者Tree的超类初始化 - 必须调用初始化init。如果将这两个操作分开,则可能存在不完整的对象,这些对象将无法按预期运行。因此,虽然可以将它们分开,但这样做是不明智的,因为Apple的init州文档是:

  

init消息与同一行代码中的alloc消息相关联

这就是Apple告诉一个小小的错误,以防止你犯一个大错误。

Objective-C还提供了一种创作的单一操作形式:

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

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

HTH