2015-05-28 4 views
1

У меня есть функция, которая переключается между UICollectionView:Как убедиться в том, что завершение будет называться в animateWithDuration()

func toggleCollectionView(target: NSObject, targetName:String){ 
    self.view.userInteractionEnabled = false 
    if let tempTarget = target as? UICollectionView { 
     //if selected item is same as active one, won't do anything 
     if(targetName != activeToolbarName){ 

      tempTarget.hidden = false 
      tempTarget.frame.origin.y = screenSize.height 
      UIView.animateWithDuration(0.4, delay: 0.0, options: .CurveEaseOut, animations: { 
       if let tempActiveToolbar = self.activeToolbar as? UICollectionView { 
        tempActiveToolbar.frame.origin.y = self.screenSize.height 
       } 

       tempTarget.frame.origin.y = self.screenSize.height - tempTarget.frame.height - self.selectorsContainer.frame.height 
       }, completion: { finished in 
        if let tempActiveToolbar = self.activeToolbar as? UICollectionView { 
         tempActiveToolbar.hidden = true 
         self.activeToolbar = target 
         self.activeToolbarName = targetName 
         self.view.userInteractionEnabled = true 

        } 

      }) 
     } 

    } 

} 

Это срабатывает на несколько кнопки на экране, как это:

@IBAction func showFontsTool(sender: UIBarButtonItem) { 
    toggleCollectionView(fontsCV, targetName:"fontsCV") 
} 

Если пользователь нажимает на кнопки очень быстро, блок completion не будет вызываться иногда, а self.view.userInteractionEnabled не будет включен. Как я могу убедиться, что блок completion будет вызываться всегда после запуска анимации?

Update

Исправлена ​​функция, которая работает отлично:

func toggleCollectionView(target: NSObject, targetName:String){ 

    if let tempTarget = target as? UICollectionView { 
     //if selected item is same as active one, won't do anything 
     if(targetName != activeToolbarName){ 
      tempTarget.hidden = false 
      tempTarget.frame.origin.y = screenSize.height 

      if (runningAnimation == false){ 
       runningAnimation = true 
       self.activeToolbarName = targetName 
       UIView.animateWithDuration(0.4, delay: 0.0, options: .CurveEaseOut, animations: { 
        if let tempActiveToolbar = self.activeToolbar as? UICollectionView { 
         tempActiveToolbar.frame.origin.y = self.screenSize.height 
        } 

        tempTarget.frame.origin.y = self.screenSize.height - tempTarget.frame.height - self.selectorsContainer.frame.height 
        }, completion: { finished in 
         if let tempActiveToolbar = self.activeToolbar as? UICollectionView { 
          tempActiveToolbar.hidden = true 
          self.activeToolbar = target 
          self.runningAnimation = false       } 
       }) 
      } 

     } 

    } 

} 

ответ

1

Это временное решение:

Создайте булеву переменную animationTriggering, которая устанавливает себя верно, когда нажата ваша кнопка. Эта переменная может действовать как флаг для проверки; Если это правда, не выполняйте анимацию UIView во второй раз. Вы будете выполнять анимацию UIView только в том случае, если она находится в ложном состоянии.

После завершения анимации UIView установите его на значение false, чтобы в следующий раз его можно было запустить снова.

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

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

+0

Забыла упомянуть. Я советую вам установить для параметра userInteraction значение false, только если вы уверены, что собираетесь поменять его обратно на true ... Вы должны поместить его прямо перед вызовом 'UIView.animate'. –

1

Во-первых, вы должны объявить глобальную переменную Bool.

var isAnimating:BOOL = False 

Теперь в кнопку действия,

@IBAction func showFontsTool(sender: UIBarButtonItem) { 
    if(!isAnimating) //if animation is not happening then call the method 
    { 
    toggleCollectionView(fontsCV, targetName:"fontsCV") 
    } 
    else //if animation is happening then return 
    { 
    return; 
    } 

}

Теперь в методе анимации, т.е. func toggleCollectionView, установите значение для isAnimating переменной, например: -

func toggleCollectionView(target: NSObject, targetName:String){ 
    isAnimating=True //notify animation has started, so that this method don't get fire on button click 
    self.view.userInteractionEnabled = false 
    if let tempTarget = target as? UICollectionView { 
     //if selected item is same as active one, won't do anything 
     if(targetName != activeToolbarName){ 

      tempTarget.hidden = false 
      tempTarget.frame.origin.y = screenSize.height 
      UIView.animateWithDuration(0.4, delay: 0.0, options: .CurveEaseOut, animations: { 
       if let tempActiveToolbar = self.activeToolbar as? UICollectionView { 
        tempActiveToolbar.frame.origin.y = self.screenSize.height 
       } 

       tempTarget.frame.origin.y = self.screenSize.height - tempTarget.frame.height - self.selectorsContainer.frame.height 
       }, completion: { finished in 
        if let tempActiveToolbar = self.activeToolbar as? UICollectionView { 
         tempActiveToolbar.hidden = true 
         self.activeToolbar = target 
         self.activeToolbarName = targetName 
         self.view.userInteractionEnabled = true 
         isAnimating=False //now set bool value on this completion handler to false so that this method can get fired again. 

        } 

      }) 
     } 

    } 

} 
+0

Спасибо за ваш ответ. – Maysam