我刚开始(过去几天读了很多)。这是我已经堆积的一些问题,希望有人可以回答。
1。(self!= nil)签入初始化代码。为什么这样?为了防止意外访问包含在那里的一些“只运行一次”代码?从哪里来的意外访问来自?进行此类检查表明我无法控制正在发生的事情。
- (id)init {
self = [super init]
if (self != nil) {
// Code..
}
return self;
}
2。你怎么没有释放静态方法返回的东西? (或者这是我的想法)
3。 str = @怎么样?“你好!”与
不同
str = [[NSString alloc] initWithString:@"Hi there!"];
据我所知,你必须用第二种方法释放str,但不是先用?如果是这样,第一个什么时候发布?哪一个更可取(不注意打字长度)?
4. 什么是autorelease,如果iphone没有垃圾回收?我注意到在main.m中创建了一个名为“自动释放池”的东西。是[myObject autorelease];一种将myObject添加到最近的包装“自动释放池”的方法,它将释放它?基本上,一些魔法,以避免自己释放它?为何使用它?
嗯,就是现在。谢谢你的回答!
答案 0 :(得分:11)
在Objective-C中,可以从-init
返回除self之外的实例。例如,类执行此操作以强制执行单例实例,或者在类集群的情况下执行此操作。例如,NSNumber
根据传递给其初始值设定项的值的类型返回子类。因此,当您致电[[NSNumber alloc] initWithLong:long_value]
时,NSNumber
的{{1}}初始化程序会在-initWithLong:
NSNumber
之后调用,但+alloc
的子类可能是回到了oringial来电者。因此模式
self = [super init];
将NSNumber
重新分配给self
的值,以便[super init]
指向self
返回的实际实例。如果[super init]
或超级+alloc
方法失败,则init
的结果可能为[super init]
。为了避免在初始化失败的情况下产生副作用,模式就变为
nil
请注意,您必须从- (id) init {
if(self = [super init]) {
// do initialization of instance variables etc.
}
return self;
}
方法返回self
(或nil
或其他实例)。您应将自己分配给init
,您可以在做更多工作之前检查[super init]
。
您可能必须释放staic方法的返回值。您应该阅读Cocoa内存管理guide。规则通常很简单:如果您调用的方法在其签名中具有“new”,“alloc”或“copy”,则结果属于调用者,调用者必须在该实例上调用nil
或那里将是一个内存泄漏。当然,您应该在其他任何内容(即不是来自“alloc”,“new”或“copy”方法)上调用-release
来保持引用,然后调用-retain
或{{1当你完成那个实例时。
-release
,假设-autorelease
被声明为str = @"Hi there!"
,则指定字符串常量str
的地址str NSString *str;
str = [[NSString alloc ] initWithString:@“Hi there!”]; @"Hi there!" to the value of the
str variable. You do not need to retain or release string constants.
str = [[NSString alloc] initWithString:@“Hi there!”]; allocates a new string instance. The value of
str2 = [[NSString alloc ] initWithString:@“你好!”]; will be the address of this instance. Each call of
str!= str2 again will allocate a new instance. So after
str2 = @“你好!”,,
。请参阅this回答。
, while after
将接收器添加到当前str==str2
。当池耗尽时(通常在当前运行循环迭代结束时,或者手动耗尽池时),池将在池中的所有实例上调用-autorelease
。如果此NSAutoreleasPool
将保留计数降为0,则对象将被释放(并且-release
被调用),就像使用任何其他-release
一样。在iPhone上使用自动释放池通常不赞成,因为它可能会导致您在运行循环迭代结束之前将池中的许多未使用实例累积掉。如果您可以使用-dealloc
代替-release
,则通常应该这样做。再次,请参阅Cocoa内存管理guide以获取更多信息。
答案 1 :(得分:2)
self
指针是系统应该做的事情,而不是程序员。此外,许多人更喜欢将程序流的主线保持为尽可能不缩进。在这种情况下,初始化代码可以重写为:
- (id)init {
if (![super init]) {
return nil; // There is a problem so bail early.
}
// Initialisation code here.
return self
}
Will Shipley比我更好地解释了这一点。
答案 2 :(得分:1)
1:此检查是为了确保超级构造函数返回一个新对象。
2:静态方法不引用实例
3:
str = @"Hi there!"
这将指定常量字符串“Hi there!”的地址。指针str
str = [[NSString alloc] initWithString:@"Hi there!"];
这会分配一个字符串并复制“Hi There!”它。这意味着a)str是可修改的,b)完成后需要解除分配。
答案 3 :(得分:1)
调用
self = [super init];
如果超类由于某种原因而无法初始化自身,包括内存不可用或某些先决条件未得到满足,则可能返回nil。如果是这种情况,你不想尝试设置self的变量,或者将self设置为委托,或者将self添加到数组中,如果self为nil。
自动释放池是在iPhone发送应用程序的每个事件时创建的。它是在任何代码运行之前创建的,并在所有代码完成后为每个事件发布。您调用autorelease
的任何对象都将被放入当前的自动释放池中。在代码完成后,自动释放池中的任何对象将被添加多次。通过这种方式,您不必担心谁负责释放由一个方法创建的对象并返回到另一个方法。
您可以根据需要创建自己的自动释放池。
str = [[NSString alloc] initWithString:@"Hi there!"];
此行创建一个不在自动释放池中的字符串,因此您必须手动释放它。只需写作
@"Hi there!";
返回一个你不必担心释放的字符串。扩展您之前的示例:
str = [[[NSString alloc] initWithString:@"Hi there!"] autorelease];
是创建字符串的另一种方法,您不必担心释放。
垃圾收集和自动释放池之间的一个区别是垃圾收集与循环引用一起使用。使用自动释放池,你不希望有两个彼此保留的对象,并希望一旦没有别的东西引用它们,它们就会不再存在;他们不会。
答案 4 :(得分:1)
如果在超级初始化之后 self nil ,那么你可能已经没有内存了。你唯一合理的做法是返回零,希望事情能够在堆栈中进一步优雅地处理。
静态方法不允许在堆上分配,因此没有什么可以免费的。
在第一个实例中,字符串被编译到应用程序的数据段中,无法释放。在第二个实例中,您将从堆中分配内存并将静态字符串(从数据段)复制到其中。
这是简单的垃圾收集。至于为何使用它,简单的答案是不。由于资源有限,不建议在iPhone上使用自动释放。