强制对象在 ARC 下释放
Posted
技术标签:
【中文标题】强制对象在 ARC 下释放【英文标题】:Forcing an object to deallocate under ARC 【发布时间】:2012-10-01 09:28:55 【问题描述】:我正在开发一款 iPad 照片拼贴应用程序,它可能会同时在屏幕上绘制数百张 UIImageView
s。
有一个按钮可以让用户“重新创建”,假设在所有照片上运行for
循环到[photo removeFromSuperview]
,然后按该顺序初始化一个新批次。
我正在使用 ARC,我的控制台告诉我,我的 Photo
的 dealloc
方法直到下一批被绘制后才会被调用,这意味着我遇到了内存问题,即使我正在尝试在添加下一组之前删除第一组。
有没有办法 1) 等到所有照片都被正确地释放或 2) 强制所有照片在 ARC 下立即释放?
【问题讨论】:
Radu 是对的,一旦您删除图像视图并删除对它们的所有强引用,它们将立即被释放。这与旧的 MRC 问题不同,因为草率使用autorelease
可能会导致内存释放延迟到当前运行循环结束。如果您仍然遇到问题,您可能需要向我们展示如何创建、添加和保存对图像及其图像视图的任何引用的代码 sn-p。但是,如果我删除图像视图并创建新视图,旧视图的释放会在我创建新视图之前发生。
【参考方案1】:
您可能在不知不觉中将图像视图放入自动释放池中。您可以通过将您自己的自动释放池包裹在您的 for 循环中来解决此问题。
例如,我做了一个非常简单的测试项目,在我的顶层视图下有一个图像视图和一个按钮。当我点击按钮时,它会删除图像视图并创建一个新视图。它通过遍历顶层视图的子视图来删除图像视图。代码如下:
@implementation ViewController
- (void)viewDidLoad
[super viewDidLoad];
[self initImageView];
- (IBAction)redoWasTapped:(id)sender
[self destroyImageView];
[self initImageView];
- (void)destroyImageView
for (UIView *subview in self.view.subviews)
if ([subview isKindOfClass:[UIImageView class]])
[subview removeFromSuperview];
- (void)initImageView
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"picture.jpg"]];
imageView.frame = CGRectInset(self.view.bounds, 100, 100);
[self.view addSubview:imageView];
@end
当我在启用了“记录引用计数”的分配工具下运行此程序时,我看到在 destroyImageView
期间未释放每个已删除的图像视图。相反,它后来在运行循环调用 -[NSAutoreleasePool release]
时被释放。
然后我更改了destroyImageView
来管理它自己的自动释放池:
- (void)destroyImageView
@autoreleasepool
for (UIView *subview in self.view.subviews)
if ([subview isKindOfClass:[UIImageView class]])
[subview removeFromSuperview];
当我在 Instruments 下再次运行它时,我看到每个删除的图像视图在 destroyImageView
期间被释放,在 @autoreleasepool
块的末尾。
【讨论】:
要了解它,请阅读NSAutoreleasePool and Run Loops【参考方案2】:ARC dealloc
s 任何不再有强引用的对象。所以对于dealloc
的东西,只需将所有指向它的变量设置为nil
并确保该对象不涉及任何循环引用。
【讨论】:
是在没有更多引用后立即解除分配,还是在之后的某个时间简单地解除分配?从经验上看,它似乎会立即发生,但有什么保证吗?如果不是,则设置为 nil 实际上不会强制执行释放。 要了解它,请阅读NSAutoreleasePool and Run Loops以上是关于强制对象在 ARC 下释放的主要内容,如果未能解决你的问题,请参考以下文章