正如标题所说:在分配和初始化对象之前检查对象是否为零是否有必要或者是一种好习惯,如此?
if (!_menuFetcher) {
_menuFetcher = [[MenuFetcher alloc] init];
_menuFetcher.delegate = self;
}
我认为这称为延迟加载吗?
答案 0 :(得分:2)
延迟加载会推迟创建对象,直到您需要它为止。 UIViewController以其视图执行此操作 - 创建视图层次结构需要大量时间和内存,因此在访问视图之前不会执行此操作。您可以使用类似于您所显示的条件语句来实现延迟加载。理想情况下,您可以将其放在属性的访问器中,并在任何地方使用该属性,这样您就不会有条件。
检查对象是否存在并不是一种坏习惯,但使用属性可以限制需要执行此操作的位置数,从而简化了代码的其余部分。
在分配之前不必总是检查是否存在某些东西 - 大部分时间你应该已经知道。例如,在您的-init
方法中,您知道尚未分配任何内容,并且您可以创建新对象所需的任何对象。
答案 1 :(得分:1)
是的,这基本上可以防止重新初始化已初始化的内容。你应该总是这样做,除非你100%确定你没有重新初始化。但是,这不称为延迟加载 - 这是不同的东西。
例如,在表视图中加载图像时,使用延迟加载。您只需加载屏幕上可见的那些图像,而不是加载表视图中的所有图像。这种方法更适合加载时间,性能和内存。
答案 2 :(得分:1)
通常你在getter方法中做这样的事情。
说你有财产:
@property (nonatomic, strong) MenuFetcher *menuFetcher;
你在视图控制器中使用说,然后你可以为这个属性实现一个getter:
- (MenuFetcher *)menuFetcher
{
if (!_menuFetcher) {
_menuFetcher = [[MenuFetcher alloc] init];
_menuFetcher.delegate = self;
}
return _menuFetcher;
}
你是对的,这是一种延迟初始化(而不是加载)的形式 - 没有分配内存,也没有初始化实例直到需要它。此外,您不需要集中初始化例程,也不需要担心正在设置的对象 - 如果它不存在则会被创建 - 如果您通过将其设置为nil将其吹走,下次当某个东西需要该类型的实例时,它会再次被创建。所以在这方面它有点优雅和高效。
因此,实际上,第一次尝试通过调用self.menuFetcher
来读取属性时,如果尚未设置,则getter会注意到它为nil并为您创建并初始化它。设置后,属性不再为nil,因此getter只返回保持的对象。
如果适合您所写的内容,请使用延迟初始化。唯一需要注意的是吸气剂除了懒惰的初始化之外还做其他事情 - 如果出现问题,那些具有“副作用”的吸气剂会很痛苦。保持简单和专注。
答案 3 :(得分:1)
这取决于。
如果您只需要实例化一个新对象,则无需检查是否为零。
在分配对象之前无需检查nil。一点也不。
但是,这是一个非常好且广泛传播的模式,您可以在实际使用对象之前检查nil。如果引用为nil,那么您可以“动态”创建它。您必须在以下代码的上下文中查看它(在此处或在调用者中)。有_menuFetcher将以某种方式使用。 (至少大多数probabyl。)
或者这是一种可以在视图控制器中多次调用的方法,如viewWillAppear
。您可能有充分的理由不早期实例化并初始化该对象,并且只需将其实例化一次。在下一次调用该方法时,您只需重用之前创建的对象。
(我的意思是首先在评论中写这个,而不是答案。但是很快就会发表评论。)
答案 4 :(得分:0)
延迟加载意味着“按需加载”,只有在真正需要时才执行操作,如下所示:
- (MenuFetcher *)instance{
if (_menuFetcher == nil){
_menuFetcher = [[MenuFetcher alloc] init];
}
return _menuFetcher;
}