Objective-C 中的延迟实例化

问题描述 投票:0回答:4

我知道在 Objective-C 中所有属性都是以 nil 开始的,并且向 nil 发送消息不会执行任何操作,因此在向新创建的属性发送消息之前,必须使用

[[Class alloc] init];
进行初始化。

但是,如果我没有向此属性发送消息或者使用

self.property = something
设置该属性怎么办?在这些情况下我也需要分配 init 吗? 另外,UI 属性是否也以 nil 开头,例如从情节提要中拖出的
UILabel
属性?这些需要alloc init吗?

objective-c properties initialization lazy-initialization alloc
4个回答
41
投票

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

但是如果它是一个不存在的对象,那么你要在哪里创建它呢?一个非常常见的模式是惰性实例化,我之所以提到它是因为您在帖子中提到了它。

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

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

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

.m
@synthesize myArray = _myArray;

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

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

此外,这种设计模式的另一个好处是,您在需要资源之前不会创建资源,而不是在视图控制器加载或应用程序启动时一次性创建所有资源,根据需求,这可能需要花费一些时间几秒钟。


4
投票

现实是,当您这样做时

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

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

我希望这对你有帮助。


2
投票

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

关于使用

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

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

正如 Kaan Dedeoglu 指出的

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


0
投票

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

但是,为了清楚起见,我鼓励您在 init 方法中将它们明确设置为 Nil。

© www.soinside.com 2019 - 2024. All rights reserved.