Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在iPhone开发/Objective-C中初始化实例变量_Iphone_Objective C_Ios_Cocoa Touch_Design Patterns - Fatal编程技术网

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

在iPhone开发/Objective-C中初始化实例变量,iphone,objective-c,ios,cocoa-touch,design-patterns,Iphone,Objective C,Ios,Cocoa Touch,Design Patterns,作为iPhone/Objective-C开发的新手,我想问这个问题,以确保在不同的场景中正确初始化实例变量。下面,我将介绍一些场景,如果有人看到任何错误的操作,请让我知道。(注意:对于我的示例,我将使用“instanceVariable”作为我们要初始化的实例变量,它是类“InstanceVariableClass”的对象。) 场景1:在非UIViewController类中初始化 a) 新分配 在初始值设定项中,可以直接访问变量(即不通过其属性)并分配它。当您调用alloc时,新创建的对象将自

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

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

a) 新分配

在初始值设定项中,可以直接访问变量(即不通过其属性)并分配它。当您调用alloc时,新创建的对象将自动保留,这将在以后与getter和setter方法一起使用时非常有效。您不希望使用属性分配变量,即
self.instanceVariable=[[InstanceVariableClass alloc]init]
或者您将保留它两次(一次在setter方法中,一次使用alloc)

b) 参数

再次单击OK,直接访问初始值设定项中的实例变量。因为您没有分配变量,只是想拥有一个传递给您的副本,所以需要让它显式地保留自己。如果您使用了setter方法,它会为您保留它,但希望避免访问初始值设定项中的属性

c) 方便法

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

场景2:在UIViewController类中初始化

a) 新分配

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

b) 方便法

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


这就是我目前所知道的。如果有人能在我的推理中发现任何缺陷,或者想到我忘记包括的任何其他场景,请让我知道。谢谢。

您提供的所有示例都非常有效

然而,许多有经验的obj-c程序员宁愿从不直接访问实例变量,除非是在他们的set/get方法中(如果您使用
@property
@synthesis
声明实例变量,这些方法甚至可能不存在),除非有必要避免一些性能瓶颈

所以,我的构造函数通常是这样的:

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

但是,如果分析代码时发现set/get方法和autoreleass池占用了太多的CPU时间或RAM,我有时会选择完全按照您的方式编写代码。

首先,Objective-C没有类变量;只是实例变量

第二,你想得太多了。内存管理规则相对简单,与setter/getter方法和/或对象创建正交。在
-init*
方法中使用setter是一个问题,因为如果覆盖setter,可能会触发副作用。然而,如果您在
-init*
-dealoc
期间出现了setter/getter副作用,那么您可能会遇到更糟糕的体系结构问题

  • 如果你+new、+alloc、-retain或-copy[NARC]一个对象,你需要将它释放到某个地方,否则它会粘在周围(很可能会泄漏)

  • 如果setter想要保留一个对象,它将保留或复制它(视情况而定),这就是平衡保留的业务。对二传手来说,你不应该在意

  • autorelease
    不过是每个线程延迟的
    release
    。一般来说,您不必担心通过各种方便的对象实例创建方法创建的
    autorelease
    d对象,但在某些情况下,autorelease压力可能是一个真正的性能问题,使用显式+alloc/set/-release可能很有用

  • 这一点在本文中有详细的解释


    这样想:

    • 当您对iVar进行直接分配时,您不会离开调用作用域,因此,分配可能会消耗调用作用域中维护的+1保留计数(可能)

    • 当通过方法调用(点语法或其他)进行赋值时,在调用范围中维护的保留计数与setter方法中发生的事情无关。这两个需要独立维护各自的保留计数增量。也就是说,如果setter想要保留对象,它将保留它。调用方独立维护其保留计数

      • Senario 1 a)
        这是无用的c
        - (id)initWithFrame:(CGRect)frame object(InstanceVariableClass*) theInstanceVariable {
        
            self = [super initWithFrame:frame];
            if (self) {
                instanceVariable = [theInstanceVariable retain];
            }
            return self;
        }
        
        - (id)initWithFrame:(CGRect)frame {
        
            self = [super initWithFrame:frame];
            if (self) {
                instanceVariable = [[InstanceVariableClass returnInitializedObject] retain];
            }
            return self;
        }
        
        - (void) viewDidLoad // or - (void) loadView if you implemented your view programmatically
        {
            [super viewDidLoad];
        
            InstanceVariableClass *tempInstanceVariable = [[InstanceVariableClass alloc] init];
            [self setInstanceVariable: tempInstanceVariable];
            [tempInstanceVariable release];
        }
        
        - (void) viewDidLoad // or - (void) loadView if you implemented your view programmatically
        {
            [super viewDidLoad];
        
            [self setInstanceVariable: [InstanceVariableClass instanceVariableClassWithInt:1]];
        }
        
        - (id)initWithFrame:(CGRect)frame {
          self = [super initWithFrame:frame];
          if (self) {
            self.instanceArray = [NSArray array];
          }
          return self;
        }