【问题标题】:Lazy instantiation in Objective-C/ iPhone developmentObjective-C/ iPhone 开发中的延迟实例化
【发布时间】:2012-08-02 00:44:46
【问题描述】:

快速提问...嗯,我知道在 Objective-C 中所有属性都以 nil 开头,并且向 nil 发送消息没有任何作用,因此您必须使用 [[Class alloc] init]; 进行初始化。在向新创建的属性发送消息之前。但是,如果我没有向该属性发送消息,或者我使用 self.property = something 设置属性怎么办?在这些情况下我是否也需要分配 init ?此外,UI 属性是否也以 nil 开头,例如从情节提要中拖出的 UILabel 属性?这些需要alloc init吗?

感谢所有回答的人

【问题讨论】:

  • +1 非常好的问题。向 not-yet-alloc/init 属性发送消息是 OjbC 初学者的常见错误。

标签: objective-c properties initialization lazy-initialization alloc


【解决方案1】:

Stunner 很好地解释了不需要分配已经创建的初始化对象。

但如果它是一个不存在的对象,你将在哪里创建它?我提到的一个非常常见的模式是惰性实例化。

所以你想要一个 NSMutableArray 属性。您可以在使用它之前在某些方法中分配初始化它,但是您必须担心“在我需要我的数组之前是否调用了该方法?”或者“我会不会不小心再次调用它并重新初始化它。”

因此,在属性的 getter 中进行此操作是一个安全的地方。每次访问该属性时都会调用它。

.h
@property (nonatomic, strong) NSMutableArray* myArray;

.m
@synthesize myArray = _myArray;

- (NSMutableArray*)myArray
{
    if (!_myArray) {
        _myArray = [[NSMutableArray alloc] initWithCapacity:2];
    }
    return _myArray;
}

每次访问该属性时,它都会说:“myArray 是否存在?如果不存在,请创建它。如果存在,则返回我拥有的。”

此外,这种设计模式的另一个好处是,在需要资源之前,您不会创建资源,而不是在视图控制器加载或应用启动时一次性创建它们,这取决于需求,可以花几秒钟。

【讨论】:

  • 很好的回应,但我不同意在 getter 中实例化 ivars,因为这使得查询对象的存在变得不可行。相反,我建议您在 setter 中进行实例化,因为您确定您正在设置的 ivar 是否不存在,您希望它存在以便可以将其设置为一个值。因此,在调用 setter 时,您永远不会不希望它存在,而在调用 getter 时,情况并非总是如此。
  • 如果我这么晚还可以添加...如果属性具有“复制”属性,您是否需要在设置器中添加它,因为它已经获得了要使用的副本?
【解决方案2】:

现实情况是,当您执行self.myProperty = [[Class alloc] init] 时,您并没有初始化您的属性。相反,你正在初始化一个你告诉你的属性(实际上是一个指针)指向的对象。因此,如果您已经有一个已分配和初始化的对象,您不必再次分配/初始化,您可以执行 self.myProperty = object;

UI 属性不会以 nil 开始,这是因为当您在界面构建器中添加元素时,视图拥有您添加的元素,并且这些对象会自动为您初始化。这意味着如果您正在创建 IBOutlets 并将它们连接到某些属性,则不必分配/初始化。

我希望这会有所帮助。

【讨论】:

    【解决方案3】:

    我没有使用 Storyboard 的经验,但我知道当您通过 xib 文件创建对象时,当您告诉视图控制器使用 xib 文件时,所有对象都会被正确实例化。所以你不必担心在代码中分配/初始化这些对象。

    关于使用self.property = <something>,这取决于something 是什么。如果某物是任何类型的现有对象,则无需对该对象执行 alloc init,因为 self.property = ... 语法会调用属性的 setter 方法,该方法将适当地保留、复制、分配等新值给属性。

    现在任何类型的现有对象都可以是分配/初始化对象,或从便捷方法获得的自动释放对象(例如 NSString 的 stringWithFormat:)。

    正如 Kaan Dedeoglu 指出的那样,self.property = ... 语法将 ivar 指向(并保留)内存中的对象,如果该对象尚未实例化,则由您来初始化该对象。

    【讨论】:

      【解决方案4】:

      不,您不需要在您的 init 方法中 [[Class alloc]init 属性。

      但是,为了清楚起见,我建议您在 init 方法中将它们显式设置为 Nil。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-04-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-08-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多