Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

[Swift] NSViewAnimationを型安全にしておきました

More than 3 years have passed since last update.

NSViewAnimationはお手軽にビューの移動アニメーションをやるのに便利なんですが、初期化に使用する辞書の値がAnyで安全ではないので型安全にしておきました。

protocol ViewAnimationTarget {}
extension NSView: ViewAnimationTarget {}
extension NSWindow: ViewAnimationTarget {}

struct ViewAnimationAttributes {

    private(set) var animations: [NSViewAnimation.Key: Any]

    init(target: ViewAnimationTarget, startFrame: NSRect? = nil, endFrame: NSRect? = nil, effect: NSViewAnimation.EffectName? = nil ) {

        animations = [.target: target]
        animations[.startFrame] = startFrame
        animations[.endFrame] = endFrame
        animations[.effect] = effect
    }

    var startFrame: NSRect? {
        get { return animations[.startFrame] as? NSRect }
        set { animations[.startFrame] = newValue }
    }

    var endFrame: NSRect? {
        get { return animations[.endFrame] as? NSRect }
        set { animations[.endFrame] = newValue }
    }

    var effect: NSViewAnimation.EffectName? {
        get { return animations[.effect] as? NSViewAnimation.EffectName }
        set { animations[.effect] = newValue }
    }
}

class ViewAnimation: NSViewAnimation, NSAnimationDelegate {

    var completeHandler: (() -> Void)?

    init(viewAnimations: [ViewAnimationAttributes]) {

        super.init(viewAnimations: viewAnimations.map { $0.animations })
    }

    required init?(coder: NSCoder) {
        fatalError("Can not initialize with NSCoder")
    }

    /// コンプリートハンドラー付き
    func start(completeHandler: @escaping () -> Void) {

        delegate = self
        self.completeHandler = completeHandler

        start()
    }

    ///
    func animationDidEnd(_ animation: NSAnimation) {

        completeHandler?()
        delegate = nil
        completeHandler = nil
    }
}

使用例

let view1 = NSView()

// ここを別々に設定
var animeAttr1 = ViewAnimationAttributes(target: view1)
animeAttr1.startFrame = NSRect(x: 0, y: 0, width: 100, height: 100)
animeAttr1.endFrame = NSRect(x: 100, y: 100, width: 100, height: 100)
animeAttr1.effect = .fadeIn

let view2 = NSView()

// 初期化時に全部設定
let animeAttr2 = ViewAnimationAttributes(target: view2,
                                         startFrame: NSRect(x: 100, y: 100, width: 100, height: 100),
                                         endFrame: NSRect(x: 0, y: 0, width: 100, height: 100),
                                         effect: .fadeOut)

let animation = ViewAnimation(viewAnimations: [animeAttr1, animeAttr2])

animation.duration = 0.5

// コンプリートハンドラー付きstart
animation.start {
    print("Finish animation")
}
masakihori
非えんじにあ / 素人が雰囲気で書いてます
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away