在iPhone Development/Objective-C中初始化实例变量

Ser*_*nce 7 iphone cocoa-touch design-patterns objective-c ios

作为iPhone/Objective-C开发的新手,我想问这个问题,以确保我在不同场景中正确初始化实例变量.所以下面,我将介绍几个场景,如果有人看到任何错误的做法,他们可以让我知道.(注意:对于我的示例,我将使用"instanceVariable"作为我们要初始化的实例变量,它是"InstanceVariableClass"类的对象.)

场景1:在非UIViewController类中初始化

a)新分配

- (id)initWithFrame:(CGRect)frame {

    self = [super initWithFrame:frame];
    if (self) {
        instanceVariable = [[InstanceVariableClass alloc] init];
    }
    return self;
}
Run Code Online (Sandbox Code Playgroud)

在初始化程序中,可以直接访问变量(即不通过它的属性)并分配它.当您调用alloc时,将自动保留新创建的对象,这将在以后与getter和setter方法一起使用时完美地工作.您不希望使用属性分配变量,即self.instanceVariable = [[InstanceVariableClass alloc] init];或者您将保留它两次(一次在您的setter方法中,一次在alloc中).

b)参数

- (id)initWithFrame:(CGRect)frame object(InstanceVariableClass*) theInstanceVariable {

    self = [super initWithFrame:frame];
    if (self) {
        instanceVariable = [theInstanceVariable retain];
    }
    return self;
}
Run Code Online (Sandbox Code Playgroud)

再一次,可以直接访问初始化程序中的实例变量.由于您没有分配变量而只是想拥有传递给您的副本,因此您需要让它明确地保留自己.如果您已经使用了setter方法,那么它将为您保留它,但是希望避免访问初始化程序中的属性.

c)便利方法

- (id)initWithFrame:(CGRect)frame {

    self = [super initWithFrame:frame];
    if (self) {
        instanceVariable = [[InstanceVariableClass returnInitializedObject] retain];
    }
    return self;
}
Run Code Online (Sandbox Code Playgroud)

使用便捷方法返回新对象时,还需要显式保留,原因与参数相同.方便方法(如果正确实施)将自动释放它生成的新对象,因此我们不必担心双重保留它.

场景2:在UIViewController类中初始化

a)新分配

- (void) viewDidLoad // or - (void) loadView if you implemented your view programmatically
{
    [super viewDidLoad];

    InstanceVariableClass *tempInstanceVariable = [[InstanceVariableClass alloc] init];
    [self setInstanceVariable: tempInstanceVariable];
    [tempInstanceVariable release];
}
Run Code Online (Sandbox Code Playgroud)

在UIViewController中,您希望在viewDidLoad方法中初始化实例变量,以使用延迟加载的实践,或仅在您需要它们的时刻加载变量.在初始化程序之外,直接访问变量是不好的做法,因此我们现在将使用我们的合成setter方法来设置变量.您不希望使用setter方法分配变量,即[self setInstanceVariable] = [[InstanceVariableClass alloc] init];,否则您将保留两次(一次在setter方法中,一次在alloc中).因此,最佳做法是创建一个新的临时变量,初始化临时变量,将实例变量设置为临时变量,然后释放临时变量.合成setter方法将为您保留变量.

b)便利方法

- (void) viewDidLoad // or - (void) loadView if you implemented your view programmatically
{
    [super viewDidLoad];

    [self setInstanceVariable: [InstanceVariableClass instanceVariableClassWithInt:1]];
}
Run Code Online (Sandbox Code Playgroud)

在初始化方法之外初始化实例变量,我们可以简单地使用我们的setter方法来设置和保留生成的对象.方便方法(如果正确实施)将自动释放它返回的对象,因此我们不必担心双重保留它.

这就是我到目前为止所拥有的.如果有人在我的推理中发现任何缺陷,或者想到我忘记包含的任何其他情况,请告诉我.谢谢.

Abh*_*ert 2

您提供的所有示例都完全有效。

然而,许多经验丰富的 obj-c 程序员宁愿直接访问实例变量,除非在其 set/get 方法内部(如果使用@propertyand声明它们,这些方法甚至可能不存在@synthesize),除非有必要避免某些性能瓶颈。

所以,我的构造函数通常看起来像这样:

- (id)initWithFrame:(CGRect)frame {
  self = [super initWithFrame:frame];
  if (self) {
    self.instanceArray = [NSArray array];
  }
  return self;
}
Run Code Online (Sandbox Code Playgroud)

但有时,如果分析代码显示 set/get 方法和自动释放池占用了过多的 CPU 时间或 RAM,我有时会选择完全按照您所做的那样编写代码。