强制对象在 ARC 下释放

Posted

技术标签:

【中文标题】强制对象在 ARC 下释放【英文标题】:Forcing an object to deallocate under ARC 【发布时间】:2012-10-01 09:28:55 【问题描述】:

我正在开发一款 iPad 照片拼贴应用程序,它可能会同时在屏幕上绘制数百张 UIImageViews。

有一个按钮可以让用户“重新创建”,假设在所有照片上运行for 循环到[photo removeFromSuperview],然后按该顺序初始化一个新批次。

我正在使用 ARC,我的控制台告诉我,我的 Photodealloc 方法直到下一批被绘制后才会被调用,这意味着我遇到了内存问题,即使我正在尝试在添加下一组之前删除第一组。

有没有办法 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 deallocs 任何不再有强引用的对象。所以对于dealloc 的东西,只需将所有指向它的变量设置为nil 并确保该对象不涉及任何循环引用。

【讨论】:

是在没有更多引用后立即解除分配,还是在之后的某个时间简单地解除分配?从经验上看,它似乎会立即发生,但有什么保证吗?如果不是,则设置为 nil 实际上不会强制执行释放。 要了解它,请阅读NSAutoreleasePool and Run Loops

以上是关于强制对象在 ARC 下释放的主要内容,如果未能解决你的问题,请参考以下文章

如何强制 Django 模型从内存中释放

iOS 6.0需要在ARC下释放GCD队列吗?

ARC 和自动释放

如何强制 SQL Server 释放内存?

linux下,如何查看工控机的串口被哪个线程占用,能否使该线程强制释放串口

移除对象时内存未释放 - 不清楚在 ARC 中释放的正确方法