swift扩展UIView实现动画依次执行

MVC框架下,如果model有连续变化,通过delegate传递给view是可能出现不一致的,因为动画的执行过程不再主线程中完成,所以实际上他是不依次执行,2个动画叠加的结果可能造成M和V的不一致,为了解决这个问题就要对动画进行排队。

这是我在这个过程中找到的资料:

https://github.com/irace/BRYSerialAnimationQueue

http://guanjinke.com

首先感谢他们对我的帮助。

我的设想解决方案是直接使用

extension UIView

来扩展一个可以实现排队执行动画的方法。

在学习了BRYSerialAnimationQueue以后遇到的主要问题是,扩展不允许使用存储属性,不过在http://guanjinke.com找到 了解决办法使用

objc_getAssociatedObject

以及

objc_setAssociatedObject

下面附具体的代码及使用:

import UIKit


private var QUEUE_NUMBER_ID = UnsafePointer<Void>()

private var SEMAPHONE_NUMBER_ID = UnsafePointer<Void>()

extension UIView {

    //添加一个存储属性,感谢http://guanjinke.com

    class var queue:dispatch_queue_t{

        get{

            var result = objc_getAssociatedObject(self, &QUEUE_NUMBER_ID) as? dispatch_queue_t

            if result == nil {

                //log("shit,I queue have not be inited!")

                //NSLog("shit,I queue have not be inited!", NSUTF8StringEncoding)

                 objc_setAssociatedObject(self, &QUEUE_NUMBER_ID, dispatch_queue_create("queue", DISPATCH_QUEUE_SERIAL), objc_AssociationPolicy(OBJC_ASSOCIATION_RETAIN))

                //return dispatch_queue_create("queue", DISPATCH_QUEUE_SERIAL)

            }

            return objc_getAssociatedObject(self, &QUEUE_NUMBER_ID)! as dispatch_queue_t

        }

        set{

            objc_setAssociatedObject(self, &QUEUE_NUMBER_ID, newValue, objc_AssociationPolicy(OBJC_ASSOCIATION_RETAIN))

        }

    }

    class var semaphore:dispatch_semaphore_t{

        get{

            var result = objc_getAssociatedObject(self, &SEMAPHONE_NUMBER_ID) as? dispatch_semaphore_t

            if result == nil {

                //NSLog("shit,I semaphore have not be inited!", NSUTF8StringEncoding)

                objc_setAssociatedObject(self, &SEMAPHONE_NUMBER_ID, dispatch_semaphore_create(0), objc_AssociationPolicy(OBJC_ASSOCIATION_RETAIN))

                //return dispatch_semaphore_create(0)

            }

            return objc_getAssociatedObject(self, &SEMAPHONE_NUMBER_ID)! as dispatch_semaphore_t

        }

        set{

            objc_setAssociatedObject(self, &SEMAPHONE_NUMBER_ID, newValue, objc_AssociationPolicy(OBJC_ASSOCIATION_RETAIN))

            //NSLog("semaphore set", NSUTF8StringEncoding)

        }

    }

    

    class func performAnimationsSerially(animation: ()->Void ) {

        dispatch_async(self.queue, { ()->Void in

            self.semaphore = dispatch_semaphore_create(0)

            //dispatch_semaphore_signal(self.semaphore)

            //dispatch_semaphore_signal(self.semaphore)

            //dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER)

            dispatch_async(dispatch_get_main_queue(), animation)

            dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER)

        })

    }

    class func runCompletionBlock(completion:(Bool->Void)?,animationDidFinish finished:Bool) {

        if let c = completion {

            c(finished)

        }

        dispatch_semaphore_signal(self.semaphore);

    }

    


    class func queueAnimateWithDuration(duration:NSTimeInterval,delay:NSTimeInterval,options:UIViewAnimationOptions,animations:()->Void,completion:(Bool->Void)?){

        self.performAnimationsSerially({ ()->Void in

            UIView.animateWithDuration(duration,delay:delay,options:options, animations:animations,completion:{(finished:Bool)->Void in

                self.runCompletionBlock(completion,animationDidFinish:finished)

            })

        })

    }

    

    class func queueAnimateWithDuration(duration:NSTimeInterval,animations:()->Void,completion:(Bool->Void)?){

        self.performAnimationsSerially({ ()->Void in

            UIView.animateWithDuration(duration,animations:animations,completion:{(finished:Bool)->Void in

                self.runCompletionBlock(completion,animationDidFinish:finished)

            })

        })

    }

    


    class func queueAnimateWithDuration(duration:NSTimeInterval,animations:()->Void){

        self.performAnimationsSerially({ ()->Void in

            UIView.animateWithDuration(duration, animations:animations,completion:{(finished:Bool)->Void in

                self.runCompletionBlock(nil,animationDidFinish:true)

            })

        })

    }

    

    class func animateWithDuration(duration: NSTimeInterval, delay: NSTimeInterval, usingSpringWithDamping dampingRatio: CGFloat, initialSpringVelocity velocity: CGFloat, options: UIViewAnimationOptions, animations: () -> Void, completion: ((Bool) -> Void)){

        self.performAnimationsSerially({ ()->Void in

            UIView.animateWithDuration(duration, delay: delay, usingSpringWithDamping: dampingRatio, initialSpringVelocity: velocity, options: options, animations: animations, completion: {(finished:Bool)->Void in

                    self.runCompletionBlock(completion,animationDidFinish:finished)

            })

        })

    }


使用举例:

UIView.queueAnimateWithDuration(tileRefreshExpandTime, delay: tilePopDelay, options: UIViewAnimationOptions.TransitionNone,

                animations: { () -> Void in

                    // Make the tile 'pop'

                    UIView.animateWithDuration(self.tileContractTime, animations: { () -> Void in

                        tile.layer.setAffineTransform(CGAffineTransformIdentity)

                        tile.value = value

                    })

                    tile.layer.setAffineTransform(CGAffineTransformMakeScale(self.tilePopMaxScale, self.tilePopMaxScale))

                },

                completion:{ (finished: Bool) -> Void in

                    // Shrink the tile after it 'pops'

                    UIView.animateWithDuration(self.tileContractTime, animations: { () -> Void in

                        tile.layer.setAffineTransform(CGAffineTransformIdentity)

                        tile.value = value

                    })

            })



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值