Help us understand the problem. What is going on with this article?

アニメーション処理が楽になるSwift拡張メソッド 〜フェードイン・フェードアウト〜

More than 3 years have passed since last update.

フェードイン・フェードアウト処理は、アプリ開発していて頻出の処理だと思います。
ベタ書きでも普通に書けちゃう程度の簡単な処理なのでそうしている人が多い気がしますが、メソッド用意しておくと地味にかなり便利です。

enum FadeType: NSTimeInterval {
    case
    Normal = 0.2,
    Slow = 1.0
}

extension UIView {
   func fadeIn(type: FadeType = .Normal, completed: (() -> ())? = nil) {
        fadeIn(duration: type.rawValue, completed: completed)
    }

    /** For typical purpose, use "public func fadeIn(type: FadeType = .Normal, completed: (() -> ())? = nil)" instead of this */
   func fadeIn(duration: NSTimeInterval = FadeType.Slow.rawValue, completed: (() -> ())? = nil) {
        alpha = 0
        hidden = false
        UIView.animateWithDuration(duration,
            animations: {
                self.alpha = 1
            }) { finished in
                completed?()
        }
    }
   func fadeOut(type: FadeType = .Normal, completed: (() -> ())? = nil) {
        fadeOut(duration: type.rawValue, completed: completed)
    }
    /** For typical purpose, use "public func fadeOut(type: FadeType = .Normal, completed: (() -> ())? = nil)" instead of this */
   func fadeOut(duration: NSTimeInterval = FadeType.Slow.rawValue, completed: (() -> ())? = nil) {
        UIView.animateWithDuration(duration
            , animations: {
                self.alpha = 0
            }) { [weak self] finished in
                self?.hidden = true
                self?.alpha = 1 
                completed?()
        }
    }
}

メリット

ベタに書いていると「本当はふわっと表示させた方がベターかもだけど、面倒だからパリッと表示させちゃうこと」などもあり得ると思いますが、簡単に呼べるようにしているとそういう手抜き心を防ぎやすいです( ´・‿・`)

特に、alpha: 0の時に丁寧にhidden: trueにするのが地味に面倒に感じてました(´-ω-`)

また、 アニメーションのdurationに統一感が生まれます。 さらに、後から統一的に値を変更するのも容易です。
上の例の場合、あっさりしたところは0.2秒、じわっと切り替えたいところは1秒、と基本2通りで、どうしてもそれ以外使いたい時はduration直接指定も可能、という作りになってます。
ベタ書きだと、この管理がわりと適当になっちゃったりしがちです。特にチーム開発だと。

呼び出し

単純な呼び出し

let view = UIView()
// これだけでふわっとフェードイン
view.fadeIn(type: .Slow)
// 完了タイミングで何かしたい場合はクロージャーも記述
view.fadeIn(type: .Slow) { [weak self] in
    self?.someMethod()
}

SDWebImageと組み合わせた例

【追記】Kingfisherで次のように書くのがオススメです

imageView.kf.setImage(with: url,
                      placeholder: placeholder,
                      options: [.transition(ImageTransition.fade(1))])
  • placeholder引数は省略しても良いですが、適当な空画像を指定すると、よりキレイです
  • SDWebImageでも同様に簡単な方法があったかもしれないですが調べていません

--- 以下原文です ---

こんな感じにSDWebImageを使った処理を定義しておくと、キャッシュ済みの時は即時表示で、ダウンロードしてきた時はふわっとフェードイン表示という処理を1行で呼び出せます。

extension UIImageView {    
    func setImageSmoothly(url: NSURL, placeholderImage: UIImage?) {
        sd_setImageWithURL(url, placeholderImage: placeholderImage) { [weak self] image, error, cacheType, imageUrl in
            if error != nil {
                return
            }
            if image != nil && cacheType == .None {
                self?.fadeIn(type: FadeType.Slow)
            }
        }
    }
}

// これだけで画像をダウンロードしつつふわっとフェードイン表示できる
imageView.setImageSmoothly(url, placeholderImage: nil)

こういう共通処理はどこに書いてる?

ライブラリとして切り出すか迷うところですが、要件に合わせてオプション引数とか追加したくなるし、このあたりは自分のソースとして書いちゃった方が取り回し良く感じちゃいます。
実際、ここに載せたのも、実際のコードはもう少し複雑になってます。

Embedded Frameworkを利用

僕はこれ系はEmbedded Frameworkに定義しちゃってます。
命名は迷いつつ、UIView+Lib.swiftとしてます。
Embedded Frameworkにする場合、呼び出し可能にするために、enumとメソッドにpublic指定が必要です。
finalも付けるとベターです。
参考: Swiftのfinal・private・Whole Module Optimizationを理解しDynamic Dispatchを減らして、パフォーマンスを向上する - Qiita

メソッド名は、衝突防ぐようにプレフィックス付けた方が良いなど言われていますが、僕はライブラリとして公開とかするのでは無ければ、無くて良いかなと思っています。

Embedded Frameworkにすると名前空間分かれる言っても、特に既存クラスの拡張メソッドの場合はそれ関係無く衝突は避けられないのでやや不確実ではありますが。(importをカットすれば一応避けられるものの)

mono0926
プロフィール: https://stackoverflow.com/story/mono0926 以前開発していたJOIN US: http://joinus30.com 2015年に開発しててベストアプリにも選ばれたPlayer!: http://www.playerapp.tokyo
https://medium.com/@mono0926
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
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  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
ユーザーは見つかりませんでした