自从iOS 3以来我没有进行任何iOS开发,所以我的内存有点模糊(尽管内存管理从来都不是我挣扎过的事情,我的想法非常明确)。
我正在开始一个新项目,并且不明白为什么骨架代码的结构是这样的:
- (void)dealloc
{
[_window release];
[super dealloc];
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc]
initWithFrame:[[UIScreen mainScreen] bounds]]
autorelease];
// ... snip ...
}
_window
来自哪里?这只是访问[self window]
的另一种方式吗?我写的是:
- (void)dealloc
{
[self.window release];
[super dealloc];
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc]
initWithFrame:[[UIScreen mainScreen] bounds]];
// ... snip ...
}
我总是将从不发布到自动发布的对象中,实际上这样做通常会导致分段错误。
答案 0 :(得分:2)
在第二个示例中,您正在泄漏窗口对象,因为alloc
将为对象提供保留计数1,您通过属性为其分配_window
,该属性也将保留指定的对象它。
确实你不应该释放一个自动释放对象,但在dealloc中你释放了window
属性的iVar。您应该始终释放任何声明为retain或strong的属性。 (虽然不是在使用ARC时)。
_window
现在自动生成为属性window
的iVar。
有些人认为您不应在self.
或init
中使用dealloc
属性。
因此,我这样做的方式是:
[_window release], _window = nil;
这将在释放它之后将_window
设置为nil,确保如果任何其他线程可能想要使用它,它将调用nil
。这可以防止崩溃,但可能会产生一些奇怪的行为。这完全取决于你。
您应该转到ARC,这是一个编译器选项,可以在编译时为您添加release / autolease。如果在使用ARC时正确设置属性,则无需添加这些属性。
答案 1 :(得分:0)
所以我想出了这个(大部分)。 @property
声明具有strong
属性。显然这是ARC的新手(我实际上并没有使用),而且只是retain
的别名,所以self.window = [ ... ]
保留了对象,因此自动释放。
仍然不清楚_window
变量,但我认为它只是一个捷径。
答案 2 :(得分:0)
检查window
属性内存描述符是什么样的。我假设它是strong
/ retain
,在这种情况下,当您设置window
属性时,它的值会保留,因此需要在dealloc
中释放。
遵循您的代码路径。
[UIWindow alloc]
= retainCount为1。dealloc
中释放它,因此retainCount = 0且对象被删除您可能错过了在以后的iOS SDK中,自动合成属性会自动创建带有下划线前缀的实例变量。因此,您也可以在self.window = nil
中执行dealloc
。
答案 3 :(得分:0)
1。为什么窗口对象会被自动释放?我很确定它在旧的iOS版本中从未像现在这样。
如果窗口对象未自动释放,则会导致泄漏。因为你正在使用
self.window = [[[UIWindow alloc] ....]autorelease];
self.
语法允许调用setter函数,它会保留对象一次。因此,应该释放我们使用[UIWindow alloc]
分配的实际窗口对象,因此autorelease
。使用self.
语法的保留在概念上以dealloc发布。因此,对于一个alloc加一个retain,我们将释放两次。
_window来自哪里?这只是另一种访问方式
[self window]
。
这个问题已经讨论过了here