2014-01-31 3 views
0

Я столкнулся с тем, что, по моему мнению, является ошибкой с 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-байтового блока памяти, но столкновение больше не работает, когда это делается. Может ли кто-нибудь предложить обходной путь, который работает?

+0

Каково распределение утечек в отчетах по приборам? Анализирует ли анализатор Xcode утечку в коде? Используйте пункт меню «Продукт»> «Анализ». Обратите внимание, что как массив 'items', так и' self.view' сохраняют новые экземпляры 'view', которые вы создаете в' -doAnimation'. Если вы используете ручной подсчет ссылок вместо ARC, вы должны освободить массив 'items' и ваши экземпляры' view' в цикле 'while'. – bneely

+0

Это использование ARC, поэтому оно должно автоматически обрабатывать сохранение и выпуск. Шаблон инструментов сообщает о событии типа Malloc, но я не вижу, чтобы вызывали другие типы (извините, если я неправильно понимаю ваш вопрос). Он указывает на PhysicalKit как ответственную библиотеку, а ответственный вызывающий абонент - \t std :: __ 1 :: __ split_buffer &> :: __ split_buffer (unsigned long, unsigned long, std :: __ 1: : распределитель &). – Cosmo

+0

Вы должны иметь возможность создать тестовый проект и запустить его самостоятельно с помощью всего лишь небольшого количества дополнительного кода, если вы хотите сами убедиться в Инструментах. Вам нужно будет добавить свойства UIDynamicAnimator * animator и NSInteger dropCount, а затем вызвать doAnimation из ViewDidLoad в новом пустом проекте. – Cosmo

ответ

0

Я столкнулся с той же проблемой, но исправлена ​​утечка памяти, установив границы с помощью

addBoundaryWithIdentifier 

К сожалению настройки границы UICollisionBehavior с translatesReferenceBoundsIntoBoundary и setTranslatesReferenceBoundsIntoBoundaryWithInsets вызванных утечками для меня.

+1

Я обнаружил, что с помощью addBoundaryWithIdentifier: fromPoint: toPoint: устранена утечка. Сначала я попробовал метод addBoundaryWithIdentifier: forPath:, но, по-видимому, он сохранил объекты пути безье для каждого объекта столкновения, к которому я добавил его. Я использовал один путь безье, хранящийся в собственности, пытаясь ограничить проблему утечки, но это не помогло. Использование CGPoints, которые явно не сохранены, сделали трюк. Спасибо, что указал мне в правильном направлении. – Cosmo