Swift之信号量semaphore控制动画排序

信号量:一个计数信号,可用来资源访问的并发控制
DispatchSemaphore(value: 1)// 初始化信号量
semaphore.wait() //等待信号,信号量-1,当信号总量为0时会一直等待
semaphore.signal() //发送信号,信号量+1
例如点击一次,连续执行4次动画,控制前面的动画执行完成后才会执行后面的动画。
效果为:


1644652552241107.gif

ViewController.swift

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        for i in 0..<4 {
            carAnimation(index: i)
        }
    }
    func carAnimation(index: Int){
        var type = DirectionType.top
        switch index {
        case 0:
            type = .top
        case 1:
            type = .bottom
        case 2:
            type = .left
        default:
            type = .right
        }
        AnimateManager.shareInstance.showAlertBanner(view: self.view, dirtype: type)
    }

AnimateManager.swift中处理信号量执行过程

class AnimateManager: NSObject {

    let semaphore = DispatchSemaphore(value: 1) //初始化信号量为1
    static let shareInstance: AnimateManager = {
        let instance = AnimateManager()
        return instance
    }()
    private override init() {}
    lazy var ferrariv: FerrariView = {
        let ferr = FerrariView()
        return ferr
    }()
    
    func showAlertBanner(view: UIView, dirtype: DirectionType) {
        let curQueue = DispatchQueue(label: "curQueue")
        curQueue.async {
            self.semaphore.wait() //信号量-1
            DispatchQueue.main.async {
                self.refreshUI(view: view, dirtype:dirtype)
            }
        }
    }
    func refreshUI(view: UIView, dirtype: DirectionType) {
        view.addSubview(ferrariv)
        ferrariv.frame = view.bounds
        weak var weakself = self
        /*
         开始执行动画
         ferrariv可自行封装想要的动画效果
         */
        ferrariv.startAnimateWithDirection(direction: dirtype) {
            //动画执行完成时的回调
            weakself?.ferrariv.removeFromSuperview()
            weakself?.semaphore.signal() //信号量+1
        }
    }
}

FerrariView.swift

enum DirectionType : Int{
    case top = 0,bottom,left,right
}
class FerrariView: UIView {

    var ferrarisImagesOne = [UIImage]()
    var ferrarisImagesTwo = [UIImage]()
    var ferrarisImagesThree = [UIImage]()
    var ferrarisImagesFour = [UIImage]()
    var publicw = 300.0
    var bgImgView: UIImageView = UIImageView()
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        ferrarisImagesOne = loadImgsArr(count: 6, prefix: "ferraris")
        ferrarisImagesTwo = loadImgsArr(count: 6, prefix: "ferrarisRight")
        ferrarisImagesThree = loadImgsArr(count: 6, prefix: "ferrarisBack")
        ferrarisImagesFour = loadImgsArr(count: 6, prefix: "ferrarisLeft")
        addSubview(bgImgView)
        
    }
    
    func startAnimateWithDirection(direction:DirectionType,complete:@escaping()->()){
        switch direction {
        case .top:
            bgImgView.animationImages = ferrarisImagesOne
            startDriveAnimat(x: -publicw, y: 40*screenH/568.0, movex: (screenW*0.5+publicw*0.5), movey: 100*screenH/568.0, complete: {
                complete()
            })
        case .bottom:
            bgImgView.animationImages = ferrarisImagesTwo
            startDriveAnimat(x: -publicw, y: (200*screenH/568.0-publicw*0.5+40*screenH/568.0), movex: (screenW*0.5+publicw*0.5), movey: -100*screenH/568.0, complete: {
                complete()
            })
        case .left:
            bgImgView.animationImages = ferrarisImagesThree
            startDriveAnimat(x: publicw, y: (200*screenH/568.0-publicw*0.5+40*screenH/568.0), movex:-(screenW*0.5+publicw*0.5 - 75*screenH/568.0), movey: -100*screenH/568.0, complete: {
                complete()
            })
        default:
            bgImgView.animationImages = ferrarisImagesFour
            startDriveAnimat(x: publicw, y: -40*screenH/568.0, movex: -(screenW*0.5+publicw*0.5 - 75*screenH/568.0), movey: 100*screenH/568.0, complete: {
                complete()
            })
        }
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    func loadImgsArr(count: Int, prefix: String) -> [UIImage] {
        var imgs = [UIImage]()
        for i in 0..<count {
            let imgName: String = prefix+String(i+1)
            if let img = UIImage.init(named: imgName) {
                imgs.append(img)
            }
        }
        return imgs
    }
    
    func startDriveAnimat(x:CGFloat,y:CGFloat,movex:CGFloat,movey:CGFloat,complete:@escaping()->()) {
        bgImgView.animationDuration = 1.0
        bgImgView.startAnimating()
        bgImgView.frame = CGRect(x: x, y: y, width: publicw, height: publicw)
        bgImgView.moveXY()(movex,movey)?.animate()(2.0)
        //从一个点开到另一个点
        weak var weakself = self
        bgImgView.animationCompletion = {
            weakself?.bgImgView.moveXY()(0,0)?.animate()(1.0)
            weakself?.bgImgView.animationCompletion = {
                weakself?.bgImgView.moveXY()(movex,movey)?.makeScale()(0.01)?.animate()(2.0)?.animationCompletion = {
                    complete()
                }
            }
        }
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
禁止转载,如需转载请通过简信或评论联系作者。

推荐阅读更多精彩内容