Я столкнулся с тем, что, по моему мнению, является ошибкой с UICollisionBehavior
в UIKit
. Добавление их в массив из UIViews
приводит к утечке памяти. Я собрал простой демонстрационный проект, который создает 10 анимаций группы взглядов, падающих с гравитацией, и столкновение с границами закрывающего представления. (Код ниже.) Шаблон «Утечки» в Инструментах сообщает о девяти 64-байтовых утечках для каждого прогона.UICollisionBehavior memory leak
- (void)doAnimation
{
self.animateButton.enabled = NO;
CGFloat left = 12.0f;
NSMutableArray *items = [NSMutableArray new];
// set up an array of views and add them to the superview
while (left < self.view.bounds.size.width - 12.0f) {
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(left, 70, 32, 32)];
left += 34.0f;
[self.view addSubview:view];
view.backgroundColor = [UIColor grayColor];
[items addObject:view];
}
// create a gravityBehavior and initialize with views array
UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:items];
[self.animator addBehavior:gravity];
// create a collisionBehavior and initialize with views array
UICollisionBehavior *collision = [[UICollisionBehavior alloc] initWithItems:items];
collision.translatesReferenceBoundsIntoBoundary = YES;
[self.animator addBehavior:collision];
}
// UIDynamicAnimatorDelegate method that's called when collision animation is complete
- (void)dynamicAnimatorDidPause:(UIDynamicAnimator *)animator
{
// get a collision behavior in order to access its items for loop below
UICollisionBehavior *behavior;
for (UIDynamicBehavior *oneBehavior in animator.behaviors) {
if ([oneBehavior isKindOfClass:[UICollisionBehavior class]]) {
behavior = (UICollisionBehavior *)oneBehavior;
break;
}
}
// reset the UIDynamicAnimator property's behaviors for next run
[self.animator removeAllBehaviors];
self.dropCount++;
// remove all subviews
for (UIView *view in behavior.items) {
[view removeFromSuperview];
}
// run the animation again or break
if (self.dropCount < 10) {
[self doAnimation];
} else {
self.animateButton.enabled = YES;
}
}
Я бы очень хотел, чтобы быть в состоянии осуществить столкновения в приложении я работаю, но эта утечка делает его непригодным для использования. Я попытался сохранить свойство collisionBehavior в свойстве и повторно использовать его. Это предотвращает утечку всего одного 64-байтового блока памяти, но столкновение больше не работает, когда это делается. Может ли кто-нибудь предложить обходной путь, который работает?
Каково распределение утечек в отчетах по приборам? Анализирует ли анализатор Xcode утечку в коде? Используйте пункт меню «Продукт»> «Анализ». Обратите внимание, что как массив 'items', так и' self.view' сохраняют новые экземпляры 'view', которые вы создаете в' -doAnimation'. Если вы используете ручной подсчет ссылок вместо ARC, вы должны освободить массив 'items' и ваши экземпляры' view' в цикле 'while'. – bneely
Это использование ARC, поэтому оно должно автоматически обрабатывать сохранение и выпуск. Шаблон инструментов сообщает о событии типа Malloc, но я не вижу, чтобы вызывали другие типы (извините, если я неправильно понимаю ваш вопрос). Он указывает на PhysicalKit как ответственную библиотеку, а ответственный вызывающий абонент - \t std :: __ 1 :: __ split_buffer &> :: __ split_buffer (unsigned long, unsigned long, std :: __ 1: : распределитель &). –
Cosmo
Вы должны иметь возможность создать тестовый проект и запустить его самостоятельно с помощью всего лишь небольшого количества дополнительного кода, если вы хотите сами убедиться в Инструментах. Вам нужно будет добавить свойства UIDynamicAnimator * animator и NSInteger dropCount, а затем вызвать doAnimation из ViewDidLoad в новом пустом проекте. – Cosmo