也许这是一个愚蠢的问题,但我真的想把它弄清楚。
例如,我有以下设置:
// .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
}
答案 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
,它会分配一些内存并将其标记为Tree
但Tree
拥有的任何实例变量}或者Tree
的超类未初始化 - 必须调用初始化init
。如果将这两个操作分开,则可能存在不完整的对象,这些对象将无法按预期运行。因此,虽然可以将它们分开,但这样做是不明智的,因为Apple的init
州文档是:
init
消息与同一行代码中的alloc
消息相关联
这就是Apple告诉一个小小的错误,以防止你犯一个大错误。
Objective-C还提供了一种创作的单一操作形式:
Tree *myTree = [Tree new]; // alloc + init
然而,与Java et al 不同的是,如果你编写一个带有参数的初始化程序,你就不会自动获得带有参数的new
版本 - 你需要自己编写(作为使用alloc
的类方法和带参数的初始化器。)
HTH