在Objective-C中初始化和分配的常规方法是
NSObject *someObject = [[NSObject alloc] init];
为什么以下没有实践?
NSObject *someObject = [NSObject alloc];
[someObject init];
答案 0 :(得分:9)
主要问题是你最终可能会使用错误的对象。
init
在许多类中都很特殊,因为它可能只是释放接收器而是创建一个驻留在不同地址的新对象。所以你的someObject
然后指向错误的(未初始化的)实例。
有很多框架类使用init
方法的参数来决定哪种专用子类最好使用。对于像NSString
或NSArray
这样的类群集,这种情况经常发生,但每种对象都会发生这种情况。
您可以在其中看到初始化程序的这种特殊行为的地方是ARC:It explicitly declares that the init family of methods eats up the receiver and returns a +1 retained object。如果初始化器只是总是返回接收器,则不需要这样做。
当然,您可以通过执行另一项任务来修复您的代码:
NSObject *someObject = [NSObject alloc];
someObject = [someObject init];
这可以解决问题。但这样做也没有任何意义。
答案 1 :(得分:4)
来自对象初始化官方documentation:
因为init ...方法可能返回nil或除了显式分配的对象之外的对象,所以使用alloc或allocWithZone返回的实例是危险的:而不是初始化程序返回的实例
同一文件的另一个原因是:
初始化对象后,不应再次初始化
给出了这个例子:
NSString *aStr = [[NSString alloc] initWithString:@"Foo"];
aStr = [aStr initWithString:@"Bar"];
其中:
此示例中的第二个初始化将导致引发NSInvalidArgumentException。
答案 2 :(得分:1)
因为它不那么简单,而且更容易出错。
分配但未初始化的对象是无用的,因此将分配和初始化放在一行中是有意义的。如果它们是分开的,如果两条线不是直接相继(可能在重构之后),则更有可能出现错误和错误,这可能会在尝试使用未初始化的对象时导致错误。
alloc
和init
在单独的行中没有一个合理的理由,反对它的原因很多。
答案 3 :(得分:0)
根据我的理解,如果没有初始化分配的对象是没有意义的,
如果您首先alloc
一个对象然后计划初始化它,可能会有一种情况,您可能忘记初始化该对象并直接调用它的任何实例方法,这将导致运行时间错误。
示例:强>
NSString *str = [NSString alloc];
// Override point for customization after application launch.
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
NSLog(@"%ld",str.length);
当我运行上面的代码时,我在我的控制台中得到了这个
Did you forget to nest alloc and init?
*** Terminating app due to uncaught exception 'NSInvalidArgumentException',
reason: '*** -length only defined for abstract class. Define -[NSPlaceholderString length]!'
如果我会这样做,我仍然会得到异常,因为str没有被初始化,因为正在初始化的内容没有被str消耗或指向
[str init];
因此,如果你想在两行中完成它应该是这样的
NSObject *someObject = [NSObject alloc];
someObject = [someObject init];
但保持嵌套
总是更好NSObject *someObject = [[NSObject alloc]init];
如果您计划在单行上执行此操作,请使用new
关键字,该关键字用于在一行上分配和初始化的目的。
示例: YourClass *object_ofClass = [YourClass new];