如何确保在animateWithDuration()中调用完成

时间:2015-05-28 08:25:47

标签: ios swift

我有一个在UICollectionView:

之间切换的函数
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块?

更新

固定功能正常:

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                            }
                })
            }

        }

    }

}

2 个答案:

答案 0 :(得分:1)

这是解决方法:

创建一个布尔变量animationTriggering,在按下按钮时将其自身设置为true。这个变量可以作为你检查的标志;如果是,则不要再次执行UIView动画。只有当它处于false状态时才会执行UIView动画。

UIView动画完成后,将其设置为false,以便下次再次触发。

我猜这个问题是由多线程问题引起的。我之前遇到过这种情况而且我做到了这一点,但我真的没有信心声称我知道问题是什么。

如果我可以冒险猜测,那就是UIView动画有一个内部异步线程,如果你发送请求的速度太快,它会互相干扰。

答案 1 :(得分:1)

首先,您必须声明一个Global 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. 

                    }

            })
        }

    }

}