Принуждение объекта к освобождению в соответствии с ARC

Я работаю над приложением для iPad-коллажей для iPad, которое рисует на экране сразу сотни UIImageView.

Существует кнопка, которая позволяет пользователю "воссоздать", что позволяет запускать цикл for на [photo removeFromSuperview] на всех фотографиях и затем инициализировать новую партию в этом порядке.

Я использую ARC, и моя консоль сообщает мне, что мой метод Photo dealloc не вызывается до тех пор, пока ПОСЛЕ следующей партии не будет нарисован, что означает, что я сталкиваюсь с проблемами памяти, m пытается удалить первый набор перед добавлением следующего набора.

Есть ли способ либо: 1) подождать, пока все фотографии не будут правильно отменены или 2) заставит все фотографии деаллоковать сразу под ARC?

Ответ 1

Вероятно, вы размещаете свои изображения в пуле автозаполнения, не осознавая этого. Возможно, вы сможете исправить это, обернув свой собственный пул автозапуска вокруг вашего цикла.

Например, я сделал очень простой тестовый проект с одним видом изображения и одной кнопкой под моим видом на верхнем уровне. Когда я нажимаю кнопку, она удаляет изображение и создает новый. Он удаляет вид изображения, перейдя по надзору просмотра верхнего уровня. Здесь код:

@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

Когда я запустил это под инструментом Allocations с включенным значением "Записи ссылок на запись", я увидел, что каждый удаленный образ не был освобожден во время destroyImageView. Вместо этого он был освобожден позже, когда цикл выполнения называется -[NSAutoreleasePool release].

Затем я изменил destroyImageView, чтобы управлять собственным пулом автозапуска:

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

Когда я снова запустил его в разделе "Инструменты", я увидел, что каждый удаленный вид изображения был освобожден во время destroyImageView, в конце блока @autoreleasepool.

Ответ 2

ARC dealloc любой объект, для которого нет более сильных ссылок. Поэтому в dealloc что-то просто установите все переменные, указывающие на него, на nil и убедитесь, что объект не участвует в какой-либо циклической ссылке.