Задержка освобождения ivar после освобождения родительского объекта

#objective-c #memory-management #ivar

#objective-c #управление памятью #ivar

Вопрос:

У меня есть класс TouchInfo, который имеет ivar класса MotionStreak .

 @interface TouchInfo : NSObject {
    MotionStreak *streak;
}
...
@end
 

Этот класс в основном обрабатывает событие касания и рисует полосу движения, которая следует за касанием. Я хочу освободить экземпляр TouchInfo , который связан с определенным касанием, когда пользователь отпускает свой палец, но я хочу, чтобы полоса движения оставалась от 0,5 до 1,0 секунды, прежде чем исчезнуть, поэтому я не могу освободить streak ivar в dealloc методе TouchInfo class .

Я использую таймер для задержки выпуска streak ivar, используя пользовательский класс таймера следующим образом:

 - (void)dealloc {
    [self timedReleaseStreak];
    [super dealloc];
}

- (void)timedReleaseStreak {
    [streak fadeoutWithDelay:1.0];
    [[TimerHandler sharedTimer] object:streak action:@selector(release) delay:1.0];
}
 

Пока это работает без каких-либо сбоев. Но мне интересно, делаю ли я это неправильно, и есть ли лучший и рекомендуемый способ сделать это. Пожалуйста, дайте совет.

p / s: Пожалуйста, никаких советов по ARC; Мне еще предстоит автоматически выпустить волшебство подсчета ссылок вручную: P

Комментарии:

1. Я бы подумал, что передача ответственности другому объекту (затронутому представлению), возможно, была бы безопаснее?

Ответ №1:

Поскольку блоки сохраняют любые объекты, на которые они ссылаются при копировании, вы можете реализовать свою анимацию, используя их, что предотвратит освобождение объекта до освобождения блока.

Вот пример, который используется [UIView animateWithDuration:animations:completion:] для удаления представления и удаления его из иерархии представлений. Чтобы использовать блок завершения позже, он должен скопировать его в кучу, что приведет к сохранению представления.

 - (void)dealloc {
    UIView *localStreak = streak;
    [UIView animateWithDuration:1.0 animations:^ {
        localStreak.alpha = 0.0;
    } completion:^ (BOOL finished) {
        [localStreak removeFromSuperview];
    }];
    [streak release];
    [super dealloc];
}
 

Обратите внимание, что я скопировал streak ivar в локальную переменную и использовал ее в блоке. Если вы попытаетесь использовать ivar напрямую, вместо этого он будет сохранен self , что не сработает, потому что вы уже запускаете процесс освобождения.