funzinエンジニアはじめに19卒内定者として現在、AbemaTVで内定者アルバイトをしている中澤(@funzin)です。Animation)というライブラリを作成しました。このブログでは、なぜSicaを作成するに至ったかなどの作成秘話を綴っていきます。私事ですが、2018年度第3期の個人の目標としては以下の2点がありました。AbemaTVのiOSアプリのアニメーションを改善するもしそれが汎用化できそうであればOSSとして公開する上記の目標を達成するために、まずは現状のアニメーションについて、調査しました。iOSアプリのアニメーションについて今までAbemaTVのiOSアプリではCheetahというアニメーションライブラリを使用していました。Cheetahのメリット・デメリットとしては以下の点があげられます。Cheetahのメリットアニメーションが直感的でコーディングしやすいCheeathのデメリットCADisplayLinkを内部で使っていることもあり、asyncなどMainスレッドに他の処理が走る場合、アニメーションが崩れることがある実際にAbemaTV内で使用するアニメーションをCheetahで実装し、通常の場合と他の処理が走った場合で比較してみると通常のアニメーション他処理が入った場合のアニメーションせっかく用意したアニメーションがこのように崩れてしまうのはとても残念なことです。この問題を解決するために、Mainスレッドに処理が走っていても既存のアニメーションを崩さずにCheetahの置き換えが可能かどうか調査しました。今回は以下の3つのアニメーションで挙動を確認しました。CABasicAnimationCAKeyframeAnimationUIView.animate例として、UIView.animateで先ほどのアニメーションを実装する場合、以下のようなコードになります。})})completionによってネストが深くなるため、あまりきれいなコードとはいえないですね...また、completionが呼ばれたときに、新たなアニメーションを生成しているため、Mainスレッドで別な処理が走るとアニメーションがカクついたり、止まったりします。実際に3つのアニメーションを使用した動作GIFはこちらです。UIView.animateのみアニメーションのタイミング指定ができないので少しずれていますが、他はCheetahと同様の動きが確認できます。他の処理が走っている場合のアニメーションの動作GIFはこちらです。CABasicAnimationとCAKeyframeAnimationでは他の処理が走っても、問題なくアニメーションが実行されることがわかりました。パフォーマンス調査Cheetahを使わずに、アニメーションを再現することは可能だということがわかったので、次にパフォーマンス調査を行いました。パフォーマンスを測定するためInstrumentsを使って、以下の2点に注目しました。CPU使用率メモリ使用量Instrumentsで確認した内容をまとめると以下のようになりました。0.02~0.05MiBパフォーマンスとしては、CABasicAnimationとCAKeyframeAnimationが良かったため、今回はCABasicAnimationを元にアニメーションを実装しようと考えました。CABasicAnimationを扱う場合、いくつか使いにくい点があります。Type-safeではない例として、position.yをアニメーションしたい場合、対応する型はCGFloatですが、fromValueとtoValueがAny?型のため、予期せぬ型の変数を代入してもビルドは通ってしまいます。cgFloatToValueまた、keyPathもStringのため、入力ミスをする場合も考えられます。複数のアニメーションを組み合わせる場合、どうしてもコード量が増加してしまいます。連続アニメーションがしにくい連続アニメーションをする場合、beginTimeとduraitonを組み合わせて、アニメーションの開始時間をずらしていくようなコードを書かないといけません。例として、opacityの連続アニメーションを実行する場合、以下のようになります。nil)これらの問題を解決し、かつOSSとして汎用化できそうだったので、今回Sicaを作成しました。SicaについてSicaの主な特徴としては、以下の5つがあげられます。SwiftPM対応Type-safeにアニメーションposition.xに対してアニメーションする場合、valueにはCGFloat型のみ指定可能です。他の型を指定するとエラーがでます。.parallel)addBasicAnimationの引数であるkeyPathはAnimationKeyPath<ValueType>型で定義されており、ValueTypeは任意のkeyPathに対して紐づけたいアニメーションパラメータの型を示しています。Sicaの内部では、keyPathごとに適切な型が保持されているため、keyPathとValueTypeの紐づけを実現しています。・そのため、addBasicAnimationの引数であるfromとtoもAnimationKeyPath<ValueType>のValueTypeに紐づけることができます。並列・連続アニメーションCAAnimationGroup使用することで並列アニメーションを実行できますが、連続アニメーションは以前説明した通り、beginTimeとdurationをうまくずらしながら調整する必要があります。Sicaでは、runの引数に.sequence、.parallelを指定するだけで並列・連続アニメーションを実行できます。様々なアニメーションのタイミングに対応するようにイージング対応も行いました。addBasicAnimationの引数であるtimingFunctionを使用することで、イージングを設定できます。.parallel)Trendingまた、ありがたいことにGithubのTrendingで2位にランクインするなどかなり勢いにのっています?️(2018/7/19時点でスター数が570)さいごにiOSアプリでは、様々な方法でアニメーションをすることができますが、タイミングやパフォーマンスまで考慮するといろんなところに気を使わないといけない点が、今回の実装において最も大変でした。みなさんもぜひSicaを使って、アプリにアニメーションを導入していきましょう。AbemaTViOSSwiftfunzin2019年新卒入社。AbemaTVでiOSアプリ開発に携わっています。