Forcing an object to deallocate under ARC

匆匆过客 提交于 2019-12-18 02:41:23

问题


I'm working on an iPad photo collage app that draws perhaps hundreds of UIImageViews on the screen at once.

There is a button that lets the user "re-create", which is suppose to run a for loop to [photo removeFromSuperview] on all photos and then initialize a new batch, in that order.

I'm using ARC, and my console tells me that my Photo's dealloc method isn't being called until AFTER the next batch has been drawn, meaning I'm running into memory issues, even though I'm trying to remove the first set before adding the next set.

Is there a way to either 1) wait until all the photos have been properly dealloc'd or 2) force all the photos to dealloc immediately under ARC?


回答1:


You are probably putting your image views in an autorelease pool without realizing it. You may be able to fix this by wrapping your own autorelease pool around your for-loop.

For example, I made a very simple test project with one image view and one button under my top-level view. When I tap the button, it removes the image view and creates a new one. It removes the image view by looping over the top-level view's subviews. Here's the code:

@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

When I ran this under the Allocations instrument with “Record reference counts” enabled, I saw that each removed image view was not deallocated during destroyImageView. Instead, it was deallocated later when the run loop called -[NSAutoreleasePool release].

Then I changed destroyImageView to manage its own autorelease pool:

- (void)destroyImageView {
    @autoreleasepool {
        for (UIView *subview in self.view.subviews) {
            if ([subview isKindOfClass:[UIImageView class]]) {
                [subview removeFromSuperview];
            }
        }
    }
}

When I ran it again under Instruments, I saw that each removed image view was deallocated during destroyImageView, at the end of the @autoreleasepool block.




回答2:


ARC deallocs any object to which there are no more strong references. So to dealloc something, simply set all the variables pointing to it to nil and make sure the object is not involved in any circular reference.



来源:https://stackoverflow.com/questions/12827319/forcing-an-object-to-deallocate-under-arc

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!