iOS向けのライブラリをオープンソースプロジェクトとして公開するということ、そして依存管理ツールCocoaPods
で配布する方法について書きます。
先日、2011年から公開しているiOS向けのカラーピッカーのバージョンを2.0に上げました。
シンプルなカラーピッカーですが、使い勝手も組み込みやすさも、かなりいい感じに仕上がっているんじゃないかと思います。
http://hayashi311.github.io/Color-Picker-for-iOS/
2.0に上げるタイミングで、人にお願いしていたCocoaPodsへの登録を初めて自分で行ったので、忘れないためのメモでもあります。
git, GitHubについての説明はしません。
オープンソースで公開する理由
自己顕示欲を満たせる
これを書かなきゃ嘘だと思うんですが、オープンソースプロジェクトを公開して使ってもらうことってかなり快感です。
他の開発者がコードを読んで、自分のアプリに組み込む、これってすごいことです。
他の開発者から学べる
勝手にforkされますし、自分の使っていない環境や技術に対応するよう、IssuesやPull Requestが届きます。想定していなかった使い方や、より良い実装、typoの指摘から、初心者の質問まで。
何よりも、他の人の目を意識してコードを書くのはいい経験になります。
結構、簡単
iOSの開発環境・エコシステムはこの数年ですごく良くなりました。GitHubも最高です。
git push
で公開して、pod try
で試してもらえるんです。
pod try
を使ったことがない人は、以下のコマンドを試してみてください
pod try Color-Picker-for-iOS
オープンソースの適当さが分かる
オープンソースってすごいものだと思っていませんか。
公開してみると結構適当でもみんな使ってくれるんだなということが実感できますし、自分が他のプロジェクトを使う時もちゃんとコード読む癖が付きます。
何を公開するか
CocoaPodsを探してもなかったもの、自分が不便だと思って実装したら意外と上手く出来たものを実装するといいんじゃないでしょうか。
僕の場合は、
- 3本のUISliderを使って、RGBを選択させるようなことはしたくなかった
- 当時は微妙なカラーピッカーしかなかった(画像を使っていたり、デザインが微妙だったり
という理由で自前で実装したものを勢いで公開しました。
その後、使われ方や、流行っているプロジェクトを見て、
- 組み込みやすさ
- カスタマイズのしやすさ
- パフォーマンス
- IBフレンドリー&AutoLayout対応 (2.0
- iOS7以降のフラットデザインに変更 (2.0
というような改善を行っています。
公開していなければ考えなかったようなことなので、公開して良かったなーと思っています。
公開の準備
今、公開しようとしているコードが、まだアプリから完全に分離できていないという状態だとします。
名前を決める
これ大事です。CocoaPodsはGitHubに依存し、GitHubはリポジトリのURLにプロジェクト名が入っている関係で、名前を変えることができません。
僕は3年前にColor-Picker-for-iOS
という糞みたいな名前を付けてから変えることができていません。
- 検索しやすくて分かりやすい名前
- プレフィックスを付ける (最近は3文字推奨だそうです。インターネットで読みました
こんな感じ
プロジェクトの準備
いつからか分からないんですが、オープンソースのプロジェクトはこんな構成にすべしという指針をCocoaPodsが公開しています。
pod try
コマンドは最近実装されたばかりで、ディレクトリ構成によっては上手く動作しないこともあるみたいです。今から公開するのであれば、この指針に従って、
pod lib create [pod name]
とやるだけで、いい感じのテンプレートが生成されるそうです(やってない
ライブラリをアプリから分離する
Classes
の中に、配布するコードを入れて、Example
の中にサンプルを書きます。
Example
に書いたものが、pod try
で実行されます。
公開すると変えられないことも多いので、ここでリファクタリングもやってしまうと良いと思います。
クリーンで、疎結合で、可能な限り理解しやすいように。
流行っているプロジェクトは3行くらいで呼び出せて、カスタマイズすることができます。
参考になるプロジェクトを二つ紹介します。
AFNetworking2
は互いに依存しない小さな機能を組み合わせて、強力な機能を実現するお手本のようなプロジェクトです。ライブラリは2層になっていて、疎で個別に差し替え可能な機能群と、それを簡単に呼び出せるラッパーに分かれています。
https://github.com/AFNetworking/AFNetworking
SVProgressHUD
は良いデザインとシンプルなAPIの組み合わせが、どれだけ効果的かを示すよい例です。
SVProgressHUD
を使う時は何も考える必要がないように設計されていて、アプリ内のどこからでも高品質なHUDを1行で呼び出せます。
https://github.com/samvermette/SVProgressHUD
ライブラリを公開すると思って読むと、また違った発見があると思います。
READMEを書く
ドキュメントを書きます。
人気のライブラリのREADMEはmarkdownを駆使して読みやすいように装飾されていて、もはやREADME文学というべき何かに昇華されています。
コンセプト、スクリーンショット、サンプルコード、公開後有名アプリに採用されたら、採用実績なんかも書くといいんじゃないでしょうか。
スクリーンショットはスクリーンショット用のブランチに置くか(そして、raw.githubusercontent.com/~
をREADMEで読み込む)、GitHub Pages用のブランチにでも置いておくと、リポジトリがすっきりします。
ライセンス
ライセンスを決めます。適当に調べてみてください。
iOSのライブラリではMITライセンスが多いように思います。
テスト
UIコンポーネントを公開する場合は、なかなか書きづらいんですが、公開するものがUIを伴わないライブラリなら元のアプリのプロジェクトからテストを持ってくるとよいと思います。
さて、これで公開するライブラリの準備が整いました。
CocoaPodsでの配布
podspecを作る
pod lib create
で出来たpodspecを編集します。
pod spec lint
で正しく編集できたか確認できるのですが、Githubにtagをpushするまで通らないようです。
まず、ローカルできちんと動作するか確認する方法です。
適当なプロジェクトを作る
pod init
でPodfileを作ります。これから公開するライブラリを使う側のプロジェクトファイルというイメージです。
Podfileに以下を記述します。
platform :ios, '7.0'
pod 'ライブラリ名', :path => 'ライブラリのPath'
CocoaPodsはローカルのプロジェクトも指定することができるんです。
あとはいつも通り、
pod install
で、上手く動作して、適当なプロジェクト内からライブラリを期待通り呼び出せるまでpodspecを編集します。
GitHubで公開
GitHubで公開します。ライブラリ名と同じリポジトリ名にしてください。そうしないと、あらゆる面でCocoaPodsが上手く動作しない可能性があります。僕は3年前に(ry
先ほどのPodfileを以下のように書き換えます。
platform :ios, '7.0'
pod 'ライブラリ名', :git => 'https://github.com/GitHubアカウント/リポジトリ名.git'
もう一度、適当なプロジェクトでpod install
を実行して、動作していることを確認します。
Pull Requestを投げづらいので、最低限master
の他にdevelop
ブランチは用意します。
タグを付ける
CocoaPodsで指定できるバージョンはtagで管理されています。
git tag 1.0.0
途中で足りなくなって困るので、バージョニングにネコ科の動物の名前を使うようなことはしないように。
バージョニングの作法については以下参照。
http://semver.org/
CocoaPodsには、
pod 'Hoge', '~> 1.0.7'
と書くと、Hoge 1.0.xまで、
pod 'Hoge', '~> 1.0'
と書くと、Hoge 1.xまで最新版を取得するというルールがあります。
詳しくは以下参照。
http://guides.cocoapods.org/using/the-podfile.html
tagのバージョンとpodspecに記述するバージョンは揃えます。
問題なければ
git push 1.0.0
// or git push --tags
pod try
この段階でpod try
が動きます。
pod try 'https://github.com/GitHubアカウント/リポジトリ名.git'
pod lib lint
podspecが正しく書けているか確認します。ここまでくると、podspecをすべて正しく埋めることができるはずです。
cd ~/code/Pods/NAME
pod lib lint
いろいろ怒られると思うので、修正してpushします。
tagの方も更新しておきます。(この段階ではforce push
してもよいと思います
CocoaPods trunk
配布用の仕組みでpod trunk
というのが最近できました。これを使って公開していきます。
まず、アカウント登録
pod trunk register 自分のメール '自分の名前' --description='macbook@home'
こんな感じ。メールが飛んでくるので、リンクをクリックして確認しておきます。
pod trunk me
で名前が表示されればOKです。
いよいよ、CocoaPodsで公開します。
pod trunk push ライブラリ名.podspec
lintが通っていれば問題なくpushできるんじゃないでしょうか。
http://cocoapods.org/ で自分のライブラリを検索してみましょう。
pod try ライブラリ名
でサンプルを実行できます。
適当なプロジェクトのPodfile
を
platform :ios, '7.0'
pod "Color-Picker-for-iOS", "~> 2.0"
に書き換えてpod install
が通ることを確認します。
DogFooding
公開が終わったところで、このライブラリを最初に作ったアプリのプロジェクトに戻ります。
プロジェクトのPodfile
に作ったライブラリを加えて、アプリ内にあったコードを削除します。
これで、普段の開発の中で改善を続けることができます。
公開後
ライブラリを公開すると、コードの品質の低さに恥ずかしくなったり、直したいところが出てきたり、GitHub Pagesを作りたくなったり、IssuesやPull Requestを貰ったりしますが、そろそろWWDC 2014が始まる時間なので記事をアップします。
俺たちの戦いはこれからだ!(適当