2012-02-29 3 views
14

Я создаю класс с открытым списком для автоматического отключения для одного из моих приложений. Среди его различных особенностей заключается в том, что он может свернуть панели и может оживить их крах, как вы, возможно, видели NSSplitView.NSLayoutConstraint.constant игнорирование анимации

Поскольку я использую ограничение, я достижение этого цели путем размещения требуемой ширина = (текущая ширина) ограничения на панели, а затем установить ограничение постоянной 0 в анимированных модах:

- (NSLayoutConstraint*)newHiddenConstraintAnimated:(BOOL)animated { 
    NSLayoutConstraint * constraint = [NSLayoutConstraint constraintWithItem:self.view attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:NSWidth(self.view.frame)]; 
    constraint.priority = NSLayoutPriorityRequired; 

    CABasicAnimation * anim = [CABasicAnimation animation]; 
    anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]; 
    anim.duration = 0.2; 
    constraint.animations = [NSDictionary dictionaryWithObject:anim forKey:@"constant"]; 

    [self.view addConstraint:constraint]; 

    [(animated ? constraint.animator : constraint) setConstant:0.0]; 

    return constraint; 
} 

Это прекрасно работает. К сожалению, расширение панели позже не так хорошо.

- (void)removeHiddenConstraintAnimated:(BOOL)animated { 
    if(!animated) { 
     [self.view removeConstraint:self.hiddenConstraint]; 
    } 
    else { 
     NSLayoutConstraint * constraint = self.hiddenConstraint; 
     NSView * theView = self.view; 

     [NSAnimationContext beginGrouping]; 

     [constraint.animator setConstant:self.width]; 

     [NSAnimationContext currentContext].completionHandler = ^{ 
      [theView removeConstraint:constraint]; 
     }; 

     [NSAnimationContext endGrouping]; 
    } 

    self.hiddenConstraint = nil; 
} 

Если вставить код синхронизации, я могу видеть, что обработчик завершения срабатывает почти мгновенно, снимая ограничения, прежде чем он успевает анимировать. Установка длительности в NSAnimationContext не влияет.

Любая идея, что я могу делать неправильно здесь?

+0

Вы когда-нибудь закончили этот класс с разделенным видом? Возможность его выхода с открытым исходным кодом? –

+0

Я не планирую в данный момент. Он довольно специализирован для этого приложения, и я считаю, что «NSSplitView» в [PURRDACTED] был переработан, чтобы лучше работать с автозапуском. –

+0

Ой, есть. Что касается [redacted], у него есть такая приятная особенность в отношении автомаркета, но, конечно же, он не совместим с предыдущими объектами назад. Ну, я сделаю все, что я думаю! :) –

ответ

15

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

[NSAnimationContext beginGrouping]; 
    NSAnimationContext.currentContext.duration = animagionDuration; 
    NSAnimationContext.currentContext.completionHandler = ^{[self removeConstraint:collapseConstraint];}; 
    [collapseConstraint.animator setConstant:expandedHeight]; 
    [NSAnimationContext endGrouping]; 

Это отлично работает, но если установить обработчик завершения после -setConstant:, анимация не есть шанс бежать.

+0

Ничего себе, это действительно действительно работал. Спасибо за совет! –

+0

Совсем нет, некоторое время назад я попал в ту же проблему, и именно ваш вопрос заставил меня экспериментировать :) – skh

1

Я просто получаю в борьбу с этим материалом себя так что это может быть наивным анализ, но:

Мне кажется, что вы указываете, что анимация на свойства ограничений (в вашем еще блоке) но затем, сразу же установив ссылку на ограничение на nil (потенциально освободив его), прежде чем анимация сможет запустить.

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

Обратите внимание, что если, как это, скорее всего, я не прав, я был бы признателен за два слова о том, почему, чтобы помочь мне понять это лучше :)

+0

Разумно предположить, что представление обладает любыми ограничениями, которые вы добавляете к нему, поэтому, даже если ограничение не ссылается через свойство 'hiddenConstraint', оно должно по-прежнему ссылаться на список ограничений вида. Он также поддерживается самим блоком, поскольку блоки сохраняют значения любых переменных объекта, которые вы используете в них. –

+0

Как сказал Питер, «ограничение» является сильной ссылкой и захватывается блоком, и даже если это не было, вид сохраняет ограничение. Существуют сотни ограничений в умеренно сложном автозапуске, и подавляющее большинство ссылаются только на их собственные представления. –

+0

Спасибо, что ответили ребятам. –

3

Обработчик завершения сразу стрелять, потому что он думает, что не какой-либо есть анимации, которые нужно запустить. Я бы проверил и подтвердил, что созданная анимация все еще привязана к представлению. По умолчанию CABasicAnimation устанавливается на удаление после завершения с помощью свойства removedOnCompletion, которое он наследует от CAAnimation (который по умолчанию установлен в YES).

вы хотите

anim.removedOnCompletion = NO; 
+0

Добавление 'anim.removedOnCompletion = NO;' не имеет никакого эффекта. Хорошее предложение. –

12

Я согласен, это довольно странно, и вполне может быть ошибка. Я определенно сообщаю об этом как таковом, потому что, насколько мне известно, должен работать.

Я был в состоянии получить его на работу с помощью метода NSAnimationContext класса +runAnimationGroup:completionHandler: вместо заявлений beginGrouping и endGrouping:

[NSAnimationContext runAnimationGroup:^(NSAnimationContext* context){ 
    [constraint.animator setConstant:self.width]; 
} completionHandler:^(void){ 
    [theView removeConstraint:constraint]; 
    NSLog(@"completed"); 
}]; 
+0

Увы, это, похоже, не повлияло на мой код. Я, вероятно, сделаю радар; это, безусловно, похоже, что это должно сработать. –

+0

Это странно. Здесь определенно отлично работает. –

+0

Работал для меня тоже. – stevex

Смежные вопросы