LoginSignup
3
1

More than 5 years have passed since last update.

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

Last updated at Posted at 2017-12-23

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")
}
3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1