delay(2) swift_swift4 delay() - CSDN
  • //在iOS开发中 有许多工作需要延迟执行,应用场景会有很多,我就不一一举例了 ...func delay(_ time:TimeInterval, task:@escaping () -> ()) -> Task? { func dispatch_later(_ block:@escaping () -> ()) {

    //在iOS开发中 有许多工作需要延迟执行,应用场景会有很多,我就不一一举例了

    // MARK: - 延时函数
    typealias Task = (_ cancel : Bool) -> ()
    
    @discardableResult
    
    func delay(_ time:TimeInterval, task:@escaping () -> ()) -> Task? {
        func dispatch_later(_ block:@escaping () -> ()) {
            DispatchQueue.main.asyncAfter(
                deadline: DispatchTime.now() + Double(Int64(time * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC),
                execute: block)
        }
        var closure: (() -> Void)? = task
        var result: Task?
        let delayedClosure: Task = { cancel in
            if let internalClosure = closure {
                if (cancel == false){
                    DispatchQueue.main.async(execute: internalClosure)
                }
            }
            closure = nil
            result = nil
        }
        result = delayedClosure
        dispatch_later {
            if let delayedClosure = result {
                delayedClosure(false)
            }
        } 
        return result
    }
    
    func cancel(_ task:Task?) {
        task?(true)
    }
    
    //调用
    delay(0.1, task: {
    //你的代码
    })
    
    cancel(task: {
    
    })
    
    
    展开全文
  • Swift3.0 延时执行

    2017-04-20 10:03:16
    1.延时执行 //延时1s执行 DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + Double(Int64(1*NSEC_PER_SEC))/Double(NSEC_PER_SEC)) { //code }

    1.延时执行

    //延时1秒执行
    let time: TimeInterval = 1.0
    DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + time) { 
        //code
        print("1 秒后输出")
    }

    2.对延时执行喵神进行了较好的封装,这里我也贴出来了,供大家学习

    import Foundation
    
    typealias Task = (_ cancel : Bool) -> Void
    
    func delay(_ time: TimeInterval, task: @escaping ()->()) ->  Task? {
    
        func dispatch_later(block: @escaping ()->()) {
            let t = DispatchTime.now() + time
            DispatchQueue.main.asyncAfter(deadline: t, execute: block)
        }
        var closure: (()->Void)? = task
        var result: Task?
    
        let delayedClosure: Task = {
            cancel in
          if let internalClosure = closure {
                if (cancel == false) {
                    DispatchQueue.main.async(execute: internalClosure)
                }
            }
            closure = nil
            result = nil
        }
    
        result = delayedClosure
    
        dispatch_later {
            if let delayedClosure = result {
                delayedClosure(false)
            }
        }
      return result
    }
    
    func cancel(_ task: Task?) {
        task?(true)
    }
    
    
    /*****使用*****/
    //调用
    delay(2) { print("2 秒后输出") }
    
    
    
    //取消
    let task = delay(5) { print("拨打 110") }
    
    // 仔细想一想..
    // 还是取消为妙..
    cancel(task)
    
    摘录来自: 王巍 (onevcat). “Swifter - Swift 必备 Tips (第三版)”。 iBooks. 

    3.OC版本

     //延时
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
              //do something 
    });
    展开全文
  • swift之动画的使用

    2019-01-11 13:56:20
    参考:... 2.UIView的动画;   let v1:UIView=UIView.init() let v2:UIView=UIView.init()   UIView.transition(from: v1, to: v2, duration: 3, options: UIViewAnimationOption...

    参考:https://www.jianshu.com/p/e983b26fc011

    2.UIView的动画;

     

    let v1:UIView=UIView.init()

    let v2:UIView=UIView.init()

     

    UIView.transition(from: v1, to: v2, duration: 3, options: UIViewAnimationOptions.allowAnimatedContent) { (ist) in

                

            }

     

    UIView.animate(withDuration: 3) {

                

            }

     

    UIView.animateKeyframes(withDuration: 3, delay: 0, options: UIViewKeyframeAnimationOptions, animations: {

                

            }) { (ist) in

                

            }

     

    UIView.animate(withDuration: 3, delay: 0, options: UIViewAnimationOptions.allowAnimatedContent, animations: {

                

            }, completion: { (ist) in

                

            })

    ===========================

    3.UIImageview动画;

     

    ===============================

    4.核心动画继承自CAAnimation,包括CAPropertyAnimation(属性动画)和CAAnimationGroup(组动画)和CATransition(转场动画)

    CAPropertyAnimation包括:CAKeyframeAnimation(帧动画)和CABasicAnimation

    CABasicAnimation包含CASpringAnimation

    *****************CABasicAnimation

     

    /**
     基础动画:可以平移,旋转,缩放
     */
    
    import UIKit
    
    class LYBBasicAnimateVC: UIViewController,CAAnimationDelegate {
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
    //      basicAnimate()
            keyFrameAnimate()
        }
        
    //基础动画
        func basicAnimate(){
            //手工创建layer
      let redLayer:CALayer=CALayer.init()
       //设置背景颜色
        redLayer.backgroundColor = UIColor.red.cgColor
        //设置大小和位置
        redLayer.position = CGPoint.init(x: 100, y: 100)
        redLayer.bounds = CGRect.init(x: 0, y: 0, width: 100, height: 100)
          view.layer.addSublayer(redLayer)
            //基本动画--旋转
      //1.创建动画对象
       let basic:CABasicAnimation=CABasicAnimation.init()
          //2.设置属性 (默认绕着z轴旋转)
       // fromValue--------------起始值;
        //        toValue----------------移动到多少;
      //        byValue----------------  移动了多少
      basic.keyPath = "transform.rotation";
       //设置开始、结束值
        basic.fromValue=0.1
        basic.toValue = 0.5
          //**缩放
           basic.keyPath="transform.scale"
         basic.byValue=0.65
       //**
       basic.keyPath="position"//或者 basic.keyPath="transform.translation"
            
      basic.fromValue=NSValue.init(cgPoint: CGPoint.init(x: 0, y: 10))
        basic.toValue=NSValue.init(cgPoint: CGPoint.init(x: 10, y: 10))
            
        //2.2 设置动画时间
          basic.duration = 2
         basic.repeatCount=5//重复5次
     basic.repeatDuration=1//
       //设置代理(隐式代理)
       basic.delegate=self
       //设置动画结束后保持当前状态
     basic.isRemovedOnCompletion=true
            basic.fillMode = CAMediaTimingFillMode.forwards
            //3.添加到要作用的layer上
     redLayer.add(basic, forKey: nil)
         
        }
    
        //动画开始时间
        func animationDidStart(_ anim: CAAnimation) {
            
        }
        //动画结束时间
        func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
            
        }
        
        // 关键帧动画
        func keyFrameAnimate()
        {
             //手工创建layer
            let  redLayer:CALayer=CALayer.init()
          //设置背景颜色
         redLayer.backgroundColor = UIColor.red.cgColor
       //设置大小和位置
      redLayer.position = CGPoint.init(x: 100, y: 100)
       redLayer.bounds = CGRect.init(x: 0, y: 0, width: 100, height: 100)
         view.layer.addSublayer(redLayer)
          
          //1.创建动画对象
            let basic:CAKeyframeAnimation=CAKeyframeAnimation.init()
          //2.设置属性 (默认绕着z轴旋转)
            
            //        fromValue--------------起始值;
            
            //        toValue----------------移动到多少;
            
            //        byValue----------------  移动了多少
         basic.keyPath = "transform.rotation";
    //
    //     //**缩放
        basic.keyPath="transform.scale"
            
          //**
         basic.keyPath="position"//
            
          
            //帧的路径一,value和path只能选一个
    
            let value1: NSValue = NSValue(cgPoint: CGPoint(x: 100, y: 100))
            let value2: NSValue = NSValue(cgPoint: CGPoint(x: 200, y: 100))
            let value3: NSValue = NSValue(cgPoint: CGPoint(x: 200, y: 200))
            let value4: NSValue = NSValue(cgPoint: CGPoint(x: 100, y: 200))
            let value5: NSValue = NSValue(cgPoint: CGPoint(x: 100, y: 300))
            let value6: NSValue = NSValue(cgPoint: CGPoint(x: 200, y: 400))
            basic.values = [value1, value2, value3, value4, value5, value6]
            
       
         //创建路径对象(如果设置了path,value就被忽略了,path只对anchorpoint和position起作用)
    //        let path:UIBezierPath=UIBezierPath.init(ovalIn: CGRect.init(x: 20, y: 100, width: 300, height: 200))
    //        basic.path = path.cgPath;
            
          //速度控制函数,控制动画的节奏
            
            basic.timingFunction=CAMediaTimingFunction.init(name: CAMediaTimingFunctionName.easeInEaseOut)
           //2.2 设置动画时间
          basic.duration = 2
           basic.repeatCount=5//重复5次
         basic.repeatDuration=1//
         //设置代理(隐式代理)
          basic.delegate=self
          //设置动画结束后保持当前状态
          basic.isRemovedOnCompletion=true
            basic.fillMode = CAMediaTimingFillMode.forwards
         //3.添加到要作用的layer上
          redLayer.add(basic, forKey: nil)
      
        }
        
        
        
        
    }
    

    ************CAAnimationGroup组动画

     

     //创建组动画

            let animationGroup:CAAnimationGroup=CAAnimationGroup.init()

            //3.把子动画添加到组动画中

            animationGroup.animations = [basicAni,rotationAni,keyframeAni];

            //设置组动画时间

            animationGroup.duration = 5;

     animationGroup.autoreverses =true;//动画完成后自动重新开始,默认为NO

            //4.把组动画添加到要作用的layer上

            redLayer.add(animationGroup, forKey: nil)

    *************

     

    =============

    5.CATransaction(隐式动画)

      非rootLayer,即手动创建的layer都包含隐式动画;(position,bounds,backgroundColor,)

     CATransaction.begin()//开始动画

      CATransaction.setAnimationDuration(CFTimeInterval.init(3))//设置动画时间

       CATransaction.setDisableActions(true)//不显示动画

        //改变layer的属性,属性的改变必须放在提交动画之前

         CATransaction.commit()//提交动画

     

    ==============

     

    6.CATransition(转场动画)

    参考:https://www.jianshu.com/p/1f798a171e9a

    /**
     转场动画
     核心动画继承自CAAnimation,包括和CAPropertyAnimation(属性动画)和CAAnimationGroup(组动画)和CATransition(转场动画);
     
     CAPropertyAnimation包括:CAKeyframeAnimation(帧动画)和CABasicAnimation;
     
     CABasicAnimation包含CASpringAnimation
     ---------------------
     作者:liyubao160
     来源:CSDN
     原文:https://blog.csdn.net/u011146511/article/details/79453287
     版权声明:本文为博主原创文章,转载请附上博文链接!
     
     */
    import UIKit
    enum TransitionAnimType : Int {
        case fade = 0,              //淡入淡出
        push,                       //推挤
        reveal,                     //揭开
        moveIn,                     //覆盖
        cube,                       //立方体
        suckEffect,                 //吮吸
        oglFlip,                    //翻转
        rippleEffect,               //波纹
        pageCurl,                   //翻页
        pageUnCurl,                 //反翻页
        cameraIrisHollowOpen,       //开镜头
        cameraIrisHollowClose,      //关镜头
        curlDown,                   //下翻页
        curlUp,                     //上翻页
        flipFromLeft,               //左翻转
        flipFromRight,              //右翻转
        ramdom                      //随机
    }
    
    enum TransitionSubType : Int {
        case top = 0,               //上
        left,                       //左
        bottom,                     //下
        right,                      //右
        ramdom                      //随机
    }
    
    enum TransitionCurve : Int {
        case Default = 0,           //默认
        EaseIn,                     //缓进
        EaseOut,                    //缓出
        EaseInEaseOut,              //缓进缓出
        Linear,                     //线性
        Ramdom                      //随机
    }
    
    
    class LYBCATransitonVC: UIViewController {
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            //调用
            layerTransition(animTye: .ramdom, subType: .ramdom, curve: .Ramdom, duration: 2.0, layer: (self.view.layer))
        }
        func layerTransition(animTye: TransitionAnimType, subType: TransitionSubType, curve: TransitionCurve, duration: CGFloat, layer: CALayer) {
            let key = "transition"//
            if layer.animation(forKey: key) != nil {
                layer.removeAnimation(forKey: key)
            }
            let transition = CATransition()
            
            /// 动画时长
            transition.duration = CFTimeInterval(duration)
            
            /// 动画类型
            transition.type = CATransitionType(rawValue: animationType(animType: animTye))
            
            /// 动画方向
            transition.subtype = CATransitionSubtype(rawValue: animationSubType(subType: subType))
            
            /// 缓动函数
            transition.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName(rawValue: animationCurve(curve: curve)))
            
            /// 完成动画删除
            transition.isRemovedOnCompletion = true
            
            layer.add(transition, forKey: key)//key可以传nil
            
        }
        
       
        /// 返回动画类型
        private func animationType(animType: TransitionAnimType) -> String {
            /// 设置转场动画类型
            let animTypeArray = ["fade", "push", "reveal", "moveIn", "cube",  "suckEffect", "oglFlip", "rippleEffect", "pageCurl", "pageUnCurl", "cameraIrisHollowOpen", "cameraIrisHollowClose", "curlDown", "curlUp", "flipFromLeft", "flipFromRight", "ramdom"]
            return objectFromDataSource(array: animTypeArray, index: animType.rawValue, isRamdom: (TransitionAnimType.ramdom == animType)) as! String
        }
        /// 返回动画方向
        private func animationSubType(subType: TransitionSubType) -> String {
            let animSubTypeArray = [CATransitionSubtype.fromTop, CATransitionSubtype.fromLeft, CATransitionSubtype.fromBottom, CATransitionSubtype.fromRight]
            return objectFromDataSource(array: animSubTypeArray, index: subType.rawValue, isRamdom: (TransitionSubType.ramdom == subType)) as! String
        }
        
        /// 返回动画曲线
        private func animationCurve(curve: TransitionCurve) -> String {
            let animCurveArray = [CAMediaTimingFunctionName.default, CAMediaTimingFunctionName.easeIn, CAMediaTimingFunctionName.easeOut, CAMediaTimingFunctionName.easeInEaseOut, CAMediaTimingFunctionName.linear]
            return objectFromDataSource(array: animCurveArray, index: curve.rawValue, isRamdom: (TransitionCurve.Ramdom == curve)) as! String
        }
      
        /// 统一从数据返回对象
        private func objectFromDataSource(array: Array<Any>, index: Int, isRamdom: Bool) -> AnyObject {
            let count = array.count
            let i = isRamdom ? Int(arc4random_uniform(UInt32(count))) : index
            
            return array[i] as AnyObject
        }
       
    }
    

     

    ******自定义专场动画*******

    参考:https://blog.csdn.net/hmh007/article/details/53837859
    
    
    /***
     自定义转场动画测试vc
     
     */
    
    import UIKit
    
    class LYBAutoDefineCATransitionTextVC: UIViewController {
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            view.backgroundColor=UIColor.blue
            let buttonView=UIView.init(frame: CGRect.init(x: 0, y: 100, width: WIDTH, height: 50))
            view.addSubview(buttonView)
            let cancelBtn=UIButton.init(frame: CGRect.init(x: 20, y: 0, width: 100, height: 50))
            cancelBtn.setTitle("返回", for: UIControl.State.normal)
            cancelBtn.tag=10
            cancelBtn.addTarget(self, action: #selector(sureOrcanceBtnClick), for: UIControl.Event.touchUpInside)
            buttonView.addSubview(cancelBtn)
        }
        
    
        @objc func sureOrcanceBtnClick(sender:UIButton){
            self.dismiss(animated: true, completion: nil)
        }
    }
    
    
    
    
    
    ********
    /**
     自定义转场动画,如果把LYBAutoDefineCATransitionTextVC换成UIViewcontroller就所有控制器都使适用
     使用:
     var tetxvc:LYBAutoDefineCATransitionTextVC?//要present出来的vc
     tetxvc=LYBAutoDefineCATransitionTextVC()
     self.present(tetxvc!,animated: true, completion: nil)
     */
    import UIKit
    
    class LYBAutoDefineCATRansitionVC: LYBAutoDefineCATransitionTextVC, UIViewControllerTransitioningDelegate {
        
        override func viewDidLoad() {
            super.viewDidLoad()
       
        }
        
        // 下面这两个函数定义在UIViewControllerTransitioningDelegate协议中
        // 用于为present提供animator,
        func animationControllerForPresentedController(presented: UIViewController, presentingController presenting: UIViewController, sourceController source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
            //        也可以使用CrossDissolveAnimator,动画效果各有不同
            //        return CrossDissolveAnimator()
            return HalfWaySpringAnimator()
        }
        
        //用于为dismiss提供animator
        func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
            return LYBDismisTrasition()
        }
       
        
    
    }
    
    
    ************
    /**
     自定义转场动画的实现,presen出来时的动画
     */
    
    import UIKit
    
    class HalfWaySpringAnimator: NSObject, UIViewControllerAnimatedTransitioning {
        /// 设置动画的持续时间
        func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
            return 2
        }
        
        /// 设置动画的进行方式,附有详细注释,demo中其他地方的这个方法不再解释
        func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
            let fromViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from)
            let toViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to)
            let containerView = transitionContext.containerView
            
            // 需要关注一下from/to和presented/presenting的关系
            // For a Presentation:
            //      fromView = The presenting view.
            //      toView   = The presented view.
            // For a Dismissal:
            //      fromView = The presented view.
            //      toView   = The presenting view.
            
            var fromView = fromViewController?.view
            var toView = toViewController?.view
            
            // iOS8引入了viewForKey方法,尽可能使用这个方法而不是直接访问controller的view属性
            // 比如在form sheet样式中,我们为presentedViewController的view添加阴影或其他decoration,animator会对整个decoration view
            // 添加动画效果,而此时presentedViewController的view只是decoration view的一个子视图
            if transitionContext.responds(to: #selector(transitionContext.view(forKey:))) {
                fromView = transitionContext.view(forKey: UITransitionContextViewKey.from)
                toView = transitionContext.view(forKey: UITransitionContextViewKey.to)
            }
            
            // 我们让toview的origin.y在屏幕的一半处,这样它从屏幕的中间位置弹起而不是从屏幕底部弹起,弹起过程中逐渐变为不透明
            toView?.frame = CGRect.init(x: fromView!.frame.origin.x, y: fromView!.frame.maxY / 2, width: fromView!.frame.width, height: fromView!.frame.height)
            toView?.alpha = 0.0
            
            // 在present和,dismiss时,必须将toview添加到视图层次中
            containerView.addSubview(toView!)
            
            let transitionDuration = self.transitionDuration(using: transitionContext)
            // 使用spring动画,有弹簧效果,动画结束后一定要调用completeTransition方法
            UIView.animate(withDuration: transitionDuration, delay: 0, usingSpringWithDamping: 0.6, initialSpringVelocity: 0, options: .curveLinear, animations: { () -> Void in
                toView!.alpha = 1.0     // 逐渐变为不透明
                toView?.frame = transitionContext.finalFrame(for: toViewController!)    // 移动到指定位置
            }) { (finished: Bool) -> Void in
                let wasCancelled = transitionContext.transitionWasCancelled
                transitionContext.completeTransition(!wasCancelled)
            }
        }
     
    
    }
    
    
    **********
    /**
     消失时的专场动画,dismis时的动画,也可以设置pop时的动画
     */
    import UIKit
    
    class LYBDismisTrasition: NSObject , UIViewControllerAnimatedTransitioning {
        /// 设置动画的持续时间
        func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
            return 2
        }
        
        /// 设置动画的进行方式,附有详细注释,demo中其他地方的这个方法不再解释
        func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
            let fromViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from)
            let toViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to)
            let containerView = transitionContext.containerView
            
            // 需要关注一下from/to和presented/presenting的关系
            // For a Presentation:
            //      fromView = The presenting view.
            //      toView   = The presented view.
            // For a Dismissal:
            //      fromView = The presented view.
            //      toView   = The presenting view.
            
            var fromView = fromViewController?.view
            var toView = toViewController?.view
            
            // iOS8引入了viewForKey方法,尽可能使用这个方法而不是直接访问controller的view属性
            // 比如在form sheet样式中,我们为presentedViewController的view添加阴影或其他decoration,animator会对整个decoration view
            // 添加动画效果,而此时presentedViewController的view只是decoration view的一个子视图
            if transitionContext.responds(to: #selector(transitionContext.view(forKey:))) {
                fromView = transitionContext.view(forKey: UITransitionContextViewKey.from)
                toView = transitionContext.view(forKey: UITransitionContextViewKey.to)
            }
            
            // 我们让toview的origin.y在屏幕的一半处,这样它从屏幕的中间位置弹起而不是从屏幕底部弹起,弹起过程中逐渐变为不透明
    //        toView?.frame = CGRect.init(x: fromView!.frame.origin.x, y: fromView!.frame.maxY / 2, width: fromView!.frame.width, height: fromView!.frame.height)
            toView?.frame=CGRect.init(x: 0, y: 0, width: fromView!.frame.width, height: fromView!.frame.height)
            toView?.alpha = 0.0
            
            // 在present和,dismiss时,必须将toview添加到视图层次中
            containerView.addSubview(toView!)
            
            let transitionDuration = self.transitionDuration(using: transitionContext)
            // 使用spring动画,有弹簧效果,动画结束后一定要调用completeTransition方法
            UIView.animate(withDuration: transitionDuration, delay: 0, usingSpringWithDamping: 0.6, initialSpringVelocity: 0, options: .curveLinear, animations: { () -> Void in
                toView!.alpha = 1.0     // 逐渐变为不透明
                toView?.frame = transitionContext.finalFrame(for: toViewController!)    // 移动到指定位置
            }) { (finished: Bool) -> Void in
                let wasCancelled = transitionContext.transitionWasCancelled
                transitionContext.completeTransition(!wasCancelled)
            }
        }
    }
    

     let changeAnimation:CATransition=CATransition.init()

            changeAnimation.delegate = self

            changeAnimation.duration = 0.45

    //        CATransition 动画主要在过渡时使用,比如两个页面层级改变的时候添加一个转场效果。CATransition 分为两类,一类是公开的动画效果,一类是非公开的动画效果。

            /*转场动画的属性

             fade---交叉淡化过渡

             push---新视图把旧视图推出

             moveIn----新视图移动到旧视图上面

             reveal----把旧视图移开,显示下面的新视图

             cube---立体翻滚效果

             oglFlip---上下左右翻转

             

             1,公开动画效果:

             kCATransitionFade:翻页

             kCATransitionMoveIn:弹出

             kCATransitionPush:推出

             kCATransitionReveal:移除

             

             2,非公开动画效果:

             "cube":立方体

             "suckEffect":收缩效果,如布块一样被抽走

             "oglFlip":翻转

             "rippleEffect":波纹

             "pageCurl":卷页、翻页

             "cameraIrisHollowOpen":镜头开

             "cameraIrisHollowClose":镜头关

            */

     

            changeAnimation.type = "oglFlip"//专场动画的属性

            changeAnimation.subtype = kCATransitionFromRight//控制方向

            changeAnimation.timingFunction = UIViewAnimationCurveEaseInOut

     

           view.layer.addSublayer(changeAnimation)

     

    ==============imageview动画=============

     

     

     let ar:[String]=["dw","xw","h01","h02","h03","h04","h05","h06","h07","h08","h09","h10","h11","h12","h13","ho01","ho02","ho03","ho04","ho05","ho06","ho07","ho08","ho09","ho10","ho11","ho12","ho13","f01","f02","f03","f04","f05","f06","f07","f08","f09","f10","f11","f12","f13","m01","m02","m03","m04","m05","m06","m07","m08","m09","m10","m11","m12","m13"]

        var imgAr=[UIImage]()

       

        

        override func viewDidLoad() {

            super.viewDidLoad()

            for i in 0..<54{

                let im:UIImage=UIImage.init(named: ar[i])!

                imgAr.append(im)

            }

                let imagv:UIImageView=UIImageView.init(frame: CGRect.init(x: 50, y: 0, width: 50, height: 70))

           view.addSubview(imagv)

           imagv.animationImages=imgAr

            //设置动画

            imagv.animationDuration=20//动画时长

            imagv.animationRepeatCount=1//重复播放次数

           imagv.startAnimating()//开始动画

    //        imagv.stopAnimating()//停止动画

    //       let isA = imagv.isAnimating//是否正在动画

            

        }

     

    展开全文
  • 原文 ...主题 Swift table of content spring介绍 简单介绍使用spring实现动画效果 spring代码拆解  demo架构核心动画实现 spring介绍 spring 是一个基于swift写的
    
    

    table of content

    • spring介绍 
    • 简单介绍使用spring实现动画效果 
    • spring代码拆解 
      • demo架构
      • 核心动画实现

    spring介绍

    spring 是一个基于swift写的动画库,是swift目前最常用的动画库 github6000+ 

    ### spring优点:

    • 用简单的语法封装了ios UIView Animation的方法,使用起来减少了代码量
    • 添加了几种常见的动画效果如shake pop等动画
    • 支持直接在storyboard中通过配置加入动画效果

    ### 安装:

    • 手动安装:直接将项目中的spring文件夹拖入你的项目
    • pods:
        use_frameworks!
        pod 'Spring', :git => 'https://github.com/MengTo/Spring.git', :branch => 'swift2'
    

    简单介绍使用spring实现动画效果

    spring实现动画效果有2种方式,一种是在storyboard里面配置,我个人来说不喜欢这种方式,iOS开发部分前端后端,都是一个人做,动画实现放在界面中其实维护起来容易出错,并且不利于代码重用,所以我就不介绍storyboard的实现方式,有兴趣的自己看spring主页。spring提供的demo里面,code和option弹出vc使用的就是storyboard配置的方式。

    使用spring动画示例:

      //1:需要让view继承自SpringView
      var ballView: SpringView!
      //2:配置动画的运行参数
      ballView.animation = "Shake" //配置动画方式
      //配置运动曲线 这里类似于先慢后快的运动,除了原生的运动曲线外,Spring库还添加了许多自定义的运动曲线
      ballView.curve = "EaseOut" 
      //3:执行动画
      ballView.animate()
    
    

    这样就动了起来,如图:

    可选的配置参数

    Animation:动画类型

      shake
      pop
      morph
      squeeze
      wobble
      swing
      flipX
      flipY
      fall
      squeezeLeft
      squeezeRight
      squeezeDown
      squeezeUp
      slideLeft
      slideRight
      slideDown
      slideUp
      fadeIn
      fadeOut
      fadeInLeft
      fadeInRight
      fadeInDown
      fadeInUp
      zoomIn
      zoomOut
      flash
    
    

    Curve:运动曲线

      EaseIn,
      EaseOut,
      EaseInOut,
      Linear,
      Spring,
      EaseInSine,
      EaseOutSine,
      EaseInOutSine,
      EaseInQuad,
      EaseOutQuad,
      EaseInOutQuad,
      EaseInCubic,
      EaseOutCubic,
      EaseInOutCubic,
      EaseInQuart,
      EaseOutQuart,
      EaseInOutQuart,
      EaseInQuint,
      EaseOutQuint,
      EaseInOutQuint,
      EaseInExpo,
      EaseOutExpo,
      EaseInOutExpo,
      EaseInCirc,
      EaseOutCirc,
      EaseInOutCirc,
      EaseInBack,
      EaseOutBack,
      EaseInOutBack
    
    

    Properties:属性

      force
      duration
      delay
      damping
      velocity
      repeatCount
      scale
      x
      y
      rotate
    
    

    注意,并不是所有的属性都可以同时设置使用的

    spring动画的实现-序

    我们简单的看下spring动画库中的代码文件。spring1.0.3版本,spring文件夹有30个文件,其中居然还存在一些基本没用的文件,还有些文件的作用我也没仔细看。这里主要分析下spring动画实现部分的代码,最核心的类只有就3个文件

    //核心动画效果实现类
    Spring
    
    //UIView.animateWithDuration的动画的简单封装
    SpringAnimation
    
    //使用动画的入口类,本身继承自UIView,自己使用时可以通过继承SpringView,然后就可以使用spring动画特效,同时也支持Storyboard配置动画属性
    SpringView
    

    说实话个人觉得这个库写的很啰嗦,spring里面30个文件,正真核心的就3个。使用动画也很不方便,还得继承SpringView,这个算是侵入式的编程,java中strcts被spring的Controller的区别一样。要是我来写一个动画库,1个文件把动效封装一下就好了,用静态方法或是扩展方法都挺好,也不会去支持通过storyboard去配置动画。我真的会去写一个哦,计划16年写吧。15年还得更新更新babybluetooth蓝牙库。

    虽然这么说spring框架,但其实他里面的动画效果和时间函数还是挺好的,作者好像就是设计师出生,里面每个特效的参数设置的极为合理。后面我来拆一拆它每一个动画效果和时间函数的实现。

    动画效果实现

    本文中把所有spring中的动画特效类型使用原生方法实现一次

    动画效果有这些

      shake //晃动
      pop
      morph
      squeeze
      wobble
      swing
      flipX
      flipY
      fall
      squeezeLeft
      squeezeRight
      squeezeDown
      squeezeUp
      slideLeft
      slideRight
      slideDown
      slideUp
      fadeIn
      fadeOut
      fadeInLeft
      fadeInRight
      fadeInDown
      fadeInUp
      zoomIn
      zoomOut
      flash
    
    

    这段介绍暂时忽略动画的时间函数,都已线性时间函数为例

    shake

    shake是一个关键帧动画,通过定义左右左右2次的数值变化实现晃动效果,这个效果使用原生代码实现如下

      let force = 1
      let duration = 0.7
      let delay = 0
      let repeatCount:Float = 1.0
      let timeFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
      let animation = CAKeyframeAnimation()
      animation.keyPath = "position.x"
      animation.values = [0, 30*force, -30*force, 30*force, 0]
      animation.keyTimes = [0, 0.2, 0.4, 0.6, 0.8, 1]
      animation.timingFunction =  timeFunction
      animation.duration = CFTimeInterval(duration)
      animation.additive = true
      animation.repeatCount = repeatCount
      animation.beginTime = CACurrentMediaTime() + CFTimeInterval(delay)
      ballView.layer.addAnimation(animation, forKey: "shake")
    
    

    pop

       let force:Float = 1.0
      let duration = 0.7
      let delay = 0
      let repeatCount:Float = 1.0
      let timeFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
      let animation = CAKeyframeAnimation()
      animation.keyPath = "transform.scale"
      animation.values = [0, 0.2 * force, -0.2 * force, 0.2 * force, 0]
      animation.keyTimes = [0, 0.2, 0.4, 0.6, 0.8, 1]
      animation.timingFunction = timeFunction
      animation.duration = CFTimeInterval(duration)
      animation.additive = true
      animation.repeatCount = repeatCount
      animation.beginTime = CACurrentMediaTime() + CFTimeInterval(delay)
      view.layer.addAnimation(animation, forKey: "pop")
    
    

    morph

    这个词中文应该是变形的意思,他是实现是做了x和y轴的scale变化

      let morphX = CAKeyframeAnimation()
      morphX.keyPath = "transform.scale.x"
      morphX.values = [1, 1.3*force, 0.7, 1.3*force, 1]
      morphX.keyTimes = [0, 0.2, 0.4, 0.6, 0.8, 1]
      morphX.timingFunction = getTimingFunction(curve)
      morphX.duration = CFTimeInterval(duration)
      morphX.repeatCount = repeatCount
      morphX.beginTime = CACurrentMediaTime() + CFTimeInterval(delay)
      layer.addAnimation(morphX, forKey: "morphX")
      let morphY = CAKeyframeAnimation()
      morphY.keyPath = "transform.scale.y"
      morphY.values = [1, 0.7, 1.3*force, 0.7, 1]
      morphY.keyTimes = [0, 0.2, 0.4, 0.6, 0.8, 1]
      morphY.timingFunction = getTimingFunction(curve)
      morphY.duration = CFTimeInterval(duration)
      morphY.repeatCount = repeatCount
      morphY.beginTime = CACurrentMediaTime() + CFTimeInterval(delay)
      layer.addAnimation(morphY, forKey: "morphY")
    
    

    squeeze

    挤压效果,这个效果和上面的很类似,只有x和y的scale参数不一样。注意这个force参数设置的位置还是很有讲究的

     //区别
     morphX.values = [1, 1.5*force, 0.5, 1.5*force, 1]
     morphY.values = [1, 0.5, 1, 0.5, 1]
    

    wobble

    摆动效果,实际上类似于shake并在shake中带一些旋转

      let animation = CAKeyframeAnimation()
      animation.keyPath = "transform.rotation"
      animation.values = [0, 0.3*force, -0.3*force, 0.3*force, 0]
      animation.keyTimes = [0, 0.2, 0.4, 0.6, 0.8, 1]
      animation.duration = CFTimeInterval(duration)
      animation.additive = true
      animation.beginTime = CACurrentMediaTime() + CFTimeInterval(delay)
      layer.addAnimation(animation, forKey: "wobble")
      let x = CAKeyframeAnimation()
      x.keyPath = "position.x"
      x.values = [0, 30*force, -30*force, 30*force, 0]
      x.keyTimes = [0, 0.2, 0.4, 0.6, 0.8, 1]
      x.timingFunction = getTimingFunction(curve)
      x.duration = CFTimeInterval(duration)
      x.additive = true
      x.repeatCount = repeatCount
      x.beginTime = CACurrentMediaTime() + CFTimeInterval(delay)
      layer.addAnimation(x, forKey: "x")
    
    

    swing

    这个词翻译过来也是摆动,我的英文也没那么好,不能给大家形象的解释swing和wobble区别。这里就当不同的摆动效果吧。spring中swing的摆动是只旋转

      let animation = CAKeyframeAnimation()
      animation.keyPath = "transform.rotation"
      animation.values = [0, 0.3*force, -0.3*force, 0.3*force, 0]
      animation.keyTimes = [0, 0.2, 0.4, 0.6, 0.8, 1]
      animation.duration = CFTimeInterval(duration)
      animation.additive = true
      animation.beginTime = CACurrentMediaTime() + CFTimeInterval(delay)
      layer.addAnimation(animation, forKey: "swing")
    
    

    FlipX,FlipY

    这两个动画是分别使用3D中x和y轴转换

      var perspective = CATransform3DIdentity
      perspective.m34 = -1.0 / layer.frame.size.width/2
      let animation = CABasicAnimation()
      animation.keyPath = "transform"
      animation.fromValue = NSValue(CATransform3D:
        CATransform3DMakeRotation(0, 0, 0, 0))
      //FlipX使用这句
      //animation.toValue = NSValue(CATransform3D:
        CATransform3DConcat(perspective,CATransform3DMakeRotation(CGFloat(M_PI), 0, 1, 0)))
      //FlipY使用这句
      animation.toValue = NSValue(CATransform3D:
        CATransform3DConcat(perspective,CATransform3DMakeRotation(CGFloat(M_PI), 1, 0, 0)))
      animation.duration = CFTimeInterval(duration)
      animation.beginTime = CACurrentMediaTime() + CFTimeInterval(delay)
      animation.timingFunction = getTimingFunction(curve)
      layer.addAnimation(animation, forKey: "3d")
    
    

    fall

    这个方法是使用animateWithDuration和CGAffineTransformMakeTranslation实现的,做了y轴下降和旋转

       UIView.animateWithDuration(NSTimeInterval(duration), delay: NSTimeInterval(delay), usingSpringWithDamping: damping, initialSpringVelocity: velocity, options: [.CurveLinear,.AllowUserInteraction], animations: { () -> Void in
                let translate = CGAffineTransformMakeTranslation(0, 300)
                let rotate = CGAffineTransformMakeRotation(15 * CGFloat(M_PI / 180))
                self.view.transform = CGAffineTransformConcat(translate, rotate)
            }, completion: nil)
    

    squeezeLeft,squeezeRight,squeezeDown,squeezeUp,slideLeft,slideRight,slideDown,slideUp

    这组方法是上下左右移动,slideLeft就是普通的移动,squeeze开头的会在移动中根据方向改变x或y的sacle,是效果更加逼真一些

     UIView.animateWithDuration(NSTimeInterval(duration), delay: NSTimeInterval(delay), usingSpringWithDamping: damping, initialSpringVelocity: velocity, options: [.CurveLinear,.AllowUserInteraction], animations: { () -> Void in
      let translate = CGAffineTransformMakeTranslation(100, 0)
      //slide开头就不需要scale效果
      let scale = CGAffineTransformMakeScale(0.8, 1)
      self.view.transform = CGAffineTransformConcat(translate, scale)
      }, completion: nil)
    
    

    fadeIn,fadeOut,fadeInLeft,fadeInRight,fadeInDown,fadeInUp

    这组动画是淡入淡出效果。后面四个带方向的是淡入淡出时添加方向位移效果。代码不写了,都一样的东西,就比移动的动画代码增加了一个alpha属性的修改。这组动画任然使用animateWithDuration完成

    zoomIn,zoomOut

    方法缩小,但是在spring中附加了淡入淡出的效果。这个命名就和之前的不符合了,按照之前的方法命名习惯,这里应该分成4个方法,普通的和淡入淡出的版本

    flash

    就是repeat几次,fadeIn,fadeOut,fadeIn,fadeOut,好像在闪烁一样。这个效果spring根本没做好。

    动画类型总结

    基本动画类型就这么几种,关键帧动画,基本动画,CATransform3D和CATransform。整体来说spring的动画类型也没有很多,有的动画效果参数设置的还不错,有的动画也没做好,有很多优化的空间。

    时间函数实现

    spring动画库中扩充了原生时间函数的类型,原来只有EaseIn,EaseOut,EaseInOut,Linear四种。在spring中有很多很多种类,也有很多相似,名称也不知道如何翻译合适。我把所有的时间函数二次贝塞尔曲线画出来,大家自己看吧。

    使用一个在线贝塞尔曲线查看工具: cubic-bezier-tool

    下方有个去曲线库,旁边点击导入,把下面的json导入进去。之后就可以选择每个曲线点击执行查看运动效果了,很方便。

    {
      "ease": ".25,.1,.25,1",
      "linear": "0,0,1,1",
      "ease-in": ".42,0,1,1",
      "ease-out": "0,0,.58,1",
      "ease-in-out": ".42,0,.58,1",
      "EaseInSine": "0.47, 0, 0.745, 0.715",
      "EaseOutSine": "0.39, 0.575, 0.565, 1",
      "EaseInOutSine": "0.445, 0.05, 0.55, 0.95",
      "EaseInQuad": "0.55, 0.085, 0.68, 0.53",
      "EaseOutQuad": "0.25, 0.46, 0.45, 0.94",
      "EaseInOutQuad": "0.455, 0.03, 0.515, 0.955",
      "EaseInCubic": "0.55, 0.055, 0.675, 0.19",
      "EaseOutCubic": "0.215, 0.61, 0.355, 1",
      "EaseInOutCubic": "0.645, 0.045, 0.355, 1",
      "EaseInQuart": "0.895, 0.03, 0.685, 0.22",
      "EaseOutQuart": "0.165, 0.84, 0.44, 1",
      "EaseInOutQuart": "0.77, 0, 0.175, 1",
      "EaseInQuint": "0.755, 0.05, 0.855, 0.06",
      "EaseOutQuint": "0.23, 1, 0.32, 1",
      "EaseInOutQuint": "0.86, 0, 0.07, 1",
      "EaseInExpo": "0.95, 0.05, 0.795, 0.035",
      "EaseOutExpo": "0.19, 1, 0.22, 1",
      "EaseInOutExpo": "1, 0, 0, 1",
      "EaseInCirc": "0.6, 0.04, 0.98, 0.335",
      "EaseOutCirc": "0.075, 0.82, 0.165, 1",
      "EaseInOutCirc": "0.785, 0.135, 0.15, 0.86",
      "EaseInBack": "0.6, -0.28, 0.735, 0.045",
      "EaseOutBack": "0.175, 0.885, 0.32, 1.275",
      "EaseInOutBack": "0.68, -0.55, 0.265, 1.55"
    }
    

    所有时间曲线的函数图如下

    spring library中我们能学到的内容总结

    • 最值得我们学习的地方:spring中定义的各种动画效果和时间函数的实现,所有不是全都很有用,但是还是有很多好用的地方
    • demo里面有很多细节,比如modal页面中presention和presenting的交互,通过 UIApplication.sharedApplication().sendAction("minimizeView:", to: nil, from: self, forEvent: nil) 和委托实现 
    • 其他还有很多细节,自己看源码去吧


    展开全文
  • Swift编程的15个技巧

    2019-07-05 10:06:53
    自2014年9月1.0版发布后,Savvy的应用开发团队就开始在iOS项目中实验并使用Swift。不过由于Swift相对还很新,当时大多项目仍在使用Objective-C;自从2015年9月Swift 2.0版本发布以来,我们已经开始改用Swift来编译新...
  • swift简单动画demo

    2016-05-15 23:47:33
    动画GIF No. ... name(en) gif 1 缩放动画 ... 2 位移动画 Translation 3 旋转动画 Rotation 4 颜色动画 Color 5 弹簧动画 Spring 6 组合动画 Concat 代码import UIKitclass
  • delay &amp; delaySubscription RxSwift: delay: Returns an observable sequence by the source observable sequence shifted forward in time by a specified delay. Error events from the source ...
  • 前言: 学习Swift语法的同时, 加上一点点的小实践. 囧~ OC版本带箭头的View OC&Swift版本的Demo如果你想看看 - 熟悉swift语法 - Swift中的drawRect - 扩展阅读 - Swift源码推荐 - 一如既往的图文并茂 这里我...
  • 概述 UIView.animate 参数说明: 1. withDuration: TimeInterval 动画...2. delay:TimeInterval 动画延迟执行时间 3. usingSpringWithDamping: CGFloat 弹簧阻力,取值范围为0.0-1.0,数值越小“弹簧”振动效果越明...
  • 前几话我们实现了Review按钮的功能,今天来实现Share按钮的功能,由于两个功能的相似性,所以新建一个控制器,ShareViewController类,把ReviewViewController类的代码复制过去进行修改,share中不需要transforView...
  • 原创Blog,转载请注明出处 ...我的stackoverflow 前言:最近app中的日历小概率的在currentCalendar这个方法崩溃,看了下call tree。研究了下,是线程安全问题...之后的博客绝大部分源码会用Swift来写了。一些资料 objc
  • SwiftUI官方教程解读

    2019-08-06 11:12:41
    swiftUI简介 swiftUI是wwdc2019发布的一个新的UI框架,通过声明和修改视图来布局UI和创建流畅的动画效果。并且我们可以通过状态变量来进行数据绑定实现一次性布局;Xcode 11 内建了直观的新设计工具canvus,在整个...
  • 之前用OC代码写过PUSH和POP的转场动画,闲来无事,将其转换成Swift语言,希望对大家有帮助,转载请注明。。。。如何实现PUSH和POP的转场动画?首先,创建一个NSObject的类,分别用来实现PUSH和POP的动画效果创建PUSH...
  • Swift 弹性动画教程

    2016-10-09 10:29:22
    原文:How To Create an Elastic Animation with Swift 作者:Daniel Tavares 译者:kmyhy 每个优雅的 iOS app 都会有一些定制的元素,定制的 UI、定制动画等等。定制、定制、定制,重要的事情重复三遍。如果你...
  • 现在的iOS开发中,有很多的动画框架可以使用,包括苹果自带的Core...今天我们就来好好聊聊UIView动画,使用Swift编写(大家可以看到我有时候用OC,有时候用Swift,现在的iOS学习的基本技能看着OC代码能写出Swif
  • 目 录 原文地址:http://www.raywenderlich.com/76020/using-uigesturerecognizer-with-swift-tutorial 泰然翻译组:。...更新提示:这篇教程已经由Caroline Begbie为适配IOS8及Swift做了更新。原帖
  • Swift_Toaster弹窗的使用

    2018-11-29 16:02:12
    这个弹窗swift4之后会报错,自己根据提示修改才能引用成功 最简单使用  Toast.init(text: "hhdsd").show()  Toast.init(text: "测试数据", delay: 1, duration: 2).show() 自己控制消失 ...
  • swift3 键盘通知事件

    2017-08-27 21:11:56
    swift3 键盘通知事件
  • swift中延迟执行

    2020-07-03 16:19:28
    self.perform(#selector(delayExecution), with: nil, afterDelay: 3) // 取消 NSObject.cancelPreviousPerformRequests(withTarget: self) // 2.timer(必须在主线程中执行) Timer.scheduledTimer(timeInterval: 3,...
  • swift 自定义弹窗AlertView 如果你的swift项目是4.0以下 pod ‘AEAlertView’, ‘1.0’ swift4.0以上 直接pod 本文介绍实现思路 源码链接 自定义弹窗 先看图 项目思路 ...
1 2 3 4 5 ... 20
收藏数 1,985
精华内容 794
热门标签
关键字:

delay(2) swift