Storyboard上で置いてるUIVisualEffectViewのブラーのかかり具合を調節、アニメーションさせる [iOS10]

## 注意
このハック的にブラー調整する方法ですが、
一回アプリを離れてホームに戻ってからアプリを再度開いた場合など
再描画が走るタイミングで、ブラーエフェクトが消えてしまいます。

僕の方では解決する方法が見つからなかったため、開発していたアプリに組み込むのは断念しました。

プロダクトの実装で使用する際はお気をつけください。

## 注意2
iOS 11.0.2 で試していたのですが、

```
UIViewAnimating::pauseAnimation()
```
を走らせた段階でクラッシュする現象が起きてしまいました。
仕様なのかバグなのか不明ですが、現状使えなさそうです。

## 環境
- iOS10

## やりたいこと
Storyborad上で置いた `UIVisualEffectView` にかかってるブラーエフェクトのかかり具合を調節したい。
かかってないところから調節したところまで、フェードインアニメーションをさせたい。

## できたもの
UIVisualEffectViewのエクステンションとして作るとこのような感じ

```UIVisualEffectView+Blur.swift
extension UIVisualEffectView {
  /**
   ブラーのかかり具合を調整
   
   （Storyboard等でブラーエフェクトが指定されてる前提）

   - parameter radius:       0.0 - 1.0
   - parameter setAlphaZero: alphaを0にするかどうか
   */
  func setBlurEffectRadius(_ radius: CGFloat = 0.3, setAlphaZero: Bool = false) {
    let anim = UIViewPropertyAnimator(duration: 1, curve: .linear) {
      self.effect = nil
    }
    // startしないと、fractionCompleteの状態の描画がされないので走らせる
    anim.startAnimation()
    anim.pauseAnimation()

    // ブラーのアニメーション位置指定をすることで、かかり具合を調節する
    anim.fractionComplete = 1 - radius

    if setAlphaZero {
      self.alpha = 0
    }
  }

  /**
   alpha値をアニメーションで1にする

   - parameter duration: アニメーション時間
   */
  func startFadeInAnimation(_ duration: TimeInterval = 1) {
    UIView.animate(withDuration: duration, delay: 0, options: .curveEaseInOut, animations: {
      self.alpha = 1
    }, completion: nil)
  }
}
```

PlaygroundsプロジェクトをGithubにあげました: https://github.com/umeruma/BlurAnimationDemo

![iPad Playgrounds Capture](https://github.com/umeruma/BlurAnimationDemo/raw/master/README%20Assets/capture02.png?raw=true)

Playgroundsファイルをzipアーカイブしたリンク先こちら
https://github.com/umeruma/BlurAnimationDemo/blob/master/BlurAnimationDemo.playground.zip?raw=true

（iPadユーザーでPlaygroundsアプリ使ってる方、
リンクから、直接iPadにPlaygroundプロジェクトをダウンロードできます。）

## やったこと
`UIVisualEffect` のブラーのかかり具合を調節するメソッドやプロパティーは用意されてない。
でも、アニメーション用メソッドを使って無理やり？ブラーの調節ができる。

[Animating Blur Radius](http://fichek.com/blog/animating-blur-radius/)

こちらの記事だと、スライダーの値(0-1)をアニメーションの経過タイミングに指定することで、ブラーのかかり具合を調節してる。

スライダーなしにブラーのかかり具合を調節したいので、単純に、

``` defineBlurRadius.swift
let anim = UIViewPropertyAnimator(duration: 1, curve: .linear) {
  self.visualEffectView.effect = nil
}

anim.fractionComplete = 0.6
```
としてみるも、なぜか反映されない。
なんでだろうと思っていたら、

[swift - Animate the fractionComplete of UIViewPropertyAnimator for blurring the background](http://stackoverflow.com/questions/41189776/animate-the-fractioncomplete-of-uiviewpropertyanimator-for-blurring-the-backgrou)

こちらのStackoverflowの回答にあるように、どうやら`UIViewPropertyAnimator`のアニメーションを走らせないと、`.fractionComplete`の値を変更してもViewの更新がされないとのこと。

てことで、回答にならって書いたら、ブラーの調整が反映された。

調節ができので、ブラーがかかってないところから任意のところまでブラーがかかるアニメーションを実装してみたのがこちら

``` animationBlurRadius.swift

// Storyborad上に置いてあるUIVisualEffectViewにつないでます
@IBOutlet weak var visualEffectView: UIVisualEffectView 


// MARK: - ここからは viewDidLoad() 内とかに書く

// ブラー調節用のアニメーター作成
let anim = UIViewPropertyAnimator(duration: 1, curve: .linear) {
  self.visualEffectView.effect = nil
}

// startしないとfractionComplete指定しても動かないので走らせる
anim.startAnimation()
// ですぐ止める
anim.pauseAnimation()

// そして明示的に指定すると、反映される
anim.fractionComplete = 0.6

// Viewの透明度0にしておく
visualEffectView.alpha = 0


// MARK: - ビューが表示した後アニメーション走らせたいので、下記はviewDidAppear(animated:) 内とかに書く

// アニメーションで透明度を変更する
UIView.animate(withDuration: 3, delay: 0, options: .curveEaseInOut, animations: {
  self.overlayEffectView.alpha = 1
}, completion: nil)
```

透明度を変更してアニメーションさせると、アニメーション中にかかってるブラーが消えるんじゃないかと思ったんだけど、消えてないように見える。