0

如果我们子类UIView化并且在这个新类的任何实例方法中,做

[self removeFromSuperview];

[foo someMessage];
_a = _a + 1;
self.b++;
for (int i = 0; i < 100000000; i++) {
    self.b++;
    //NSLog(@"b is %i", self.b);
}

会发生什么?假设超级视图是唯一声称拥有该视图所有权的视图,是否会self立即被解除分配?

第一行是发送一个foo引用外部对象的局部变量消息someMessage。第二行是一个局部变量_b。第三行是一个属性b。接下来的几行只是造成一些延迟。

在 Xcode 4.5 和 iPhone 5 (iOS 6) 上尝试,代码实际上运行没有崩溃。代码是在-touchesBegan. 只有在大延迟循环完成后,视图才会在屏幕上消失,可能是由于主循环现在调用drawRectrootViewController.view显示视图已经消失(视图在延迟循环之前已经从视图层次结构中消失,但只是没有反映在屏幕)。

如果我使循环只计数到 1000 或 10000,并NSLog在该循环内部使用,则该数字实际上可以很好地打印出来而没有任何崩溃。更新:据说该对象可能仍然可以访问一小段时间,但似乎即使是 30 秒或一分钟,代码仍然可以正常运行。

那么这是如何工作的呢?如果使用仪器,我实际上看到这个FooView对象只有在大延迟循环之后才离开“分配”表。所以奇怪的是,该FooView对象似乎直到后来才被释放,而不是在removeFromSuperView.

我也有一个[self.presentingViewController dismissViewControllerAnimated ...]that dismissed self,然后self.presentingViewController再次使用下一行,self.presentingViewController成为nil,但是如果我还添加一个循环以将整数属性递增 10000 并使用 打印出来NSLog,它也打印得很好。

4

1 回答 1

1

假设超级视图是唯一声称拥有该视图所有权的视图,self 会立即被释放吗?

是的,可能,但内存实际上并没有被重用或清除;如果释放后没有发生任何其他事情,您通常仍然可以得到看似有效的对象。

尝试:

[self removeFromSuperview];
[self performSelector:@selector(tryToCrash) withObject:nil afterDelay:0.1];

//...

- (void)tryToCrash
{
    [foo someMessage];
    _a = _a + 1;
    self.b++;
    for (int i = 0; i < 100000000; i++) {
        self.b++;
        //NSLog(@"i is %i", self.i);
    }
}

这将安排该代码在运行循环的下一次复飞之后发生,您可能会看到崩溃。主要的是你使用了一个你知道已经死了的对象,这还不是 C 的 UB 水平,但肯定不能保证给你任何特定的结果。

只有在大延迟循环完成后,视图才会在屏幕上消失,可能是由于主循环现在调用 drawRect

是的,视图只在每次通过运行循环时重绘,并且只有在它们被标记为需要它时才会重绘。超级视图将被如此标记,因为它的子视图之一已被删除。它也有可能将实际释放子视图推迟到这一点。

于 2012-09-27T19:11:11.277 回答