はじめに
iOSエンジニアの小菅です。
今回の記事は、去年末くらいから名前を聞くようになったNukeをForkして、WebPのデコード処理を組み込んだモノを開発して公開したので、それの紹介と作業手順などを書いていきます。
余談ですが、Nuke[ニューク]の意味を調べたら核兵器って意味らしいです。
Nukeと作ったものの紹介
先にNukeの紹介と作ったもののインストール方法を紹介します。
本家のNukeのレポジトリ
今回、本家がWebP対応をする予定がないとのことだったので、ForkしてそのままWebP対応した版をCocoaPodsに登録しました。
Forkして作成したレポジトリ
CococaPodsとCarthageに対応させたので以下のようにインストールできます。
# Podfile
pod 'Nuke+WebP', '~> 6.0'
# Cartfile
github 'ryokosuge/Nuke-WebP'
NukeのExampleにWebP表示の物を追加したやつもあげてあるので、是非試してみてください!
> bundle exec pod try Nuke+WebP
Updating spec repositories
Trying Nuke+WebP
Performing CocoaPods Installation
Fetching podspec for `Nuke+WebP` from `../`
Installing DFCache (4.0.2)
Installing Nuke+WebP (6.0)
Installing Preheat (3.0)
Installing libwebp (0.6.0)
Sending stats
Pod installation complete! There are 3 dependencies from the Podfile and 4 total pods installed.
Opening '/private/var/folders/yl/6188sfqd28l1klc_nxby14d40000gn/T/CocoaPods/Try/Nuke+WebP/Example/Nuke+WebP_Demo.xcworkspace'
ここから先はNuke+WebPを作った理由や、手順周りを書いていきます。
Nukeを選んだきっかけ
マンガZEROのiOSではSDWebImageを使って画像表示を行なっていました。
SDWebImageの採用理由としては以下の2点があります。
- 使い慣れている
- WebPに対応している
弊社マンガ事業部のアプリでは作品のバナー画像などの大きい画像のほとんどをWebP形式に変換して表示しています。
WebPの凄さについては以下の記事を参考にしてください。
何も苦しむことなくSDWebImageでWebPの画像を表示していましたが、UIが変わり画像をたくさん表示するようになってから表示速度が遅くなってきました。(自分の組み方があまりよろしくないというのが1番の要因なのはわかっています…)
そのことをマンガZEROのチームメンバーにも指摘され、サーバーエンジニアに画像のリサイズなどを行ってもらう傍ら、アプリ側もどうにか出来ないかなと考えていました。
そんな中、年末に以下の記事を読みました。
マンガZEROもまさに記事と同じくExtensionは使わず、画像のダウンロードと表示処理しかしていませんでした。
この記事でNukeの存在を初めて知って衝撃だったのが以下の画像です。
Alexander Grebenyuk | Programming in Swift, Objective-C.より引用
色々調べていくうちにSDWebImageから乗り換えることを考えるようになりましたが、NukeがWebP対応していなかったのでどうしても乗り換えられませんでした。
NukeはWebP対応していないかった
最近作られている画像ローダー周りのライブラリはWebP対応されていないのが多いです。
理由はAppleがWebPに対応していないからです。
NukeのレポジトリのissueでもWebPのサポートをお願いするissueがありましたが以下の理由で別ライブラリ採用を見送りました。
- mattt/WebPImageSerializationが全くメンテナンスされていない
- 4年前のcommitが最後
- Method Swizzlingを使用している
- UIImageのinitializerをSwizzlingしていたのですが、他のエンジニアがマンガZEROのメンテナンスをする際の負担になるかと思った
ただどうしてもNukeを導入したい熱が治らず、rs/SDWebImageやpinterest/PINRemoteImageのWebPのデコード処理を読んでいたら自分で書いて、なおかつNukeにも簡単に導入できると判断したので、自分で作成することにしました。
最初はそのままアプリに導入
最初はマンガZEROのiOSにそのままNukeを導入して、追加でWebPのデコード処理を書いて無事表示させることが出来ました。
一旦はそのままで大丈夫かと思っていましたが、他のアプリにも簡単に導入出来る様に本家をForkしてライブラリ化することを決めました。
弊社iOSチームはGithubのPrivateのSpecレポジトリを作っていて共有できるライブラリをそこにあげて他の人に使ってもらえるようにする文化があるので、最初はそこにあげようかと思いましたが、思い切ってpublicにあげてCocoaPodsに公開することにしました。
Forkしてからの簡単な手順
できる限り本家のソースコードを汚したくない(アップデートの追従が難しくなる)ので、自分で書くコードは別ディレクトリに書くようにしました。
- 本家repositoryからforkする
- レポジトリ名を変更する
- 今回の場合だと
ryokosuge/Nuke
からryokosuge/Nuke-WebP
に変更
- 今回の場合だと
- もくもくとWebPのデコード処理を書いていく
- 本家が対応しているものはできる限り対応していく
libwebp
がWatchOSでビルド出来なかったので諦める
- 無事実装終わったらリリース処理
- アカウント登録していない場合は
bundle exec pod trunk register [e-mail] '[your name]'
で登録処理- 自分の場合は
bundle exec pod trunk register ryo.kosuge@gmail.com 'Ryo Kosuge'
- 登録処理が完了すると
bundle exec pod trunk me
で確認できる
- 自分の場合は
bundle exec pod spec lint [ライブラリ名].podspec
でlintかけるbundle exec pod trunk push [ライブラリ名].podspec
でCocoaPodsに登録するcarthage build --no-skip-current
でbuildするcarthage archive
でフレームワークのzipを作成- GitHubのreleaseページに貼り付ける
上記の作業でほぼ公開作業が完了しました。
本家レポジトリはSwift Packge Manager
にも対応していましたが、現状自分自身が使っていないものに無理して対応するのもおかしいかと思い今回はやめました。
必要になった際に対応しようかと思いますが、すぐに対応して欲しい場合はPull Requestを投げつけてもらえればと思います。
ライブラリのソースコードを読んで学んだこと
今回は以下のレポジトリに大変お世話になりました。
お世話&参考にさせていただいた部分を紹介します。
SDWebImage && PINRemoteImage
- .podspecの書き方が勉強になった
- iOSとmacOSでの対応方法
UIImage
とNSImage
の対応方法…
- WebPのデコード処理
- PINRemoteImageとSDWebImageを見比べながら少しずつ意味調べて書いていきました
libwebp
との依存関係の解消方法- Cocoapodsには
libwebp
あるので多少は問題ありませんでしたが、Carthageの対応方法はPINRemoteImageを参考にやりました
- Cocoapodsには
Nuke
- Swiftのソースコード全般
- 依存関係の解消だったり、拡張のしやすさやテストコードなどとても勉強になりました
特にNukeのソースコードは何度も読み返しました。
ここまで簡潔に拡張可能なソースコードって書けるんだなって感動しました…。
Swiftでアプリもある程度余裕持って作れるようになって、アプリの設計に不満を感じ始めたらぜひNukeのソースコードを読んでみてください。
素晴らしい設計でした。
終わりに
ざっと作成したライブラリの紹介と手順と感想とを書かせて頂きました。
初めてのCocoaPodsへのライブラリ登録だったのでテンション上がった状態でブログ書きました。
Forkして書くことで本家のソースコード読みながら実装することが出来て楽しかったです。
今回は本家がWebPに対応する予定がないとのことだったのでForkしてそのまま登録までさせていただきましたが、また違うライブラリでForkする機会があったら今度はそのままPull Requestを出してみようかと思います。
Pull Requestお待ちしております!