iOS ライブラリを自作して Carthage CocoaPods で公開する最小限の手順

こんにちは。iOS エンジニアです。

というふうに名乗っていながら、iOS 向けのライブラリを作ったことがなかったので、やばいと思って作ってみました。
作成中の一連の流れを記事に残したいと思います。
(具体的なコードの書き方とかではないです。)

# 成果物

https://github.com/yuki0n0/WaveSlider/
以下解説するものは、こちらのライブラリを作成したときの情報に基づいています。

中身自体は大したものではないんですが、
ライブラリ公開の経験をしたかったという動機なのでお手柔らかに、、、
よかったら GitHub で **<font color="SandyBrown">Star ★</font>** つけてね。


# 作成

## 1. プロジェクト作成

Framework を選択して、次の画面で選択して、プロジェクト作る。
<img width="300" alt="プロジェクト作成スクリーンショット" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42826/9b32c241-96f4-f710-85a6-26508725a9ea.png">

## 2. コーディング

GitHub (もしくは他の git ホスティングサービスなど) にアップしたり、中身を実装したり、自由にやってください。

### サンプルプロジェクトの用意

自分のためにも、利用者のためにも、 **Example** プロジェクトを用意しておくといいかもしれません。
Example フォルダを作成し、その中に通常の iOS アプリの Xcode プロジェクトを作成しているパターンが多いようです。
Example ではなく **Demo** という名称を使用しているライブラリもありました。

また、その際のライブラリ管理ファイルの書き方は、下記のようにローカルのパスを指定するように記述します。

```rb:Podfile
target 'Example' do
  use_frameworks!
  pod "WaveSlider", :path => "../"
end
```

```:Cartfile
git "./.."
```

### 開発注意ポイント

- 公開したいクラスなどに `public` 修飾子をつける
- Bundle を利用する際は<br>
`Bundle.main...` ではなく `Bundle(for: WaveSlider.self)...` といったように書き換える。
-  etc...


## 3. 周辺ファイル

### README.md
いわずもがな用意しましょう。

### LICENSE

`LICENSE` ファイルを用意しましょう。
CocoaPods でも紹介されている、下記サイトを参考にできます。
https://choosealicense.com/

また、GitHub 上から直接 `LICENSE` ファイルを作成する場合、
下記のような選択 & 編集画面が出てくるため、わかりやすいです。
<img alt="GitHub LICENSE 選択" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42826/1073b260-fa9a-dbe5-bb75-796d10dcf51b.png">


### Shared をチェック

`Product > Scheme > Manage Schemes...` を開いて、
`Shared` のチェックをつけます。
**自分の確認した限りデフォルトでチェックがついていました。
その場合、一度チェックを外してから付け直すといいと思います。**
<img width="300" alt="Shared をチェック" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42826/e661f324-e0b8-05df-a561-be6eefb3f47c.png">


# 公開


## バージョニングの前提

[セマンティックバージョニング](https://semver.org/lang/ja/) に基づいていれば問題なさそうです。
また、Carthage はセマンティックでも `alpha` `rc` などの文字列が続くものは[サポートされていません](https://github.com/Carthage/Carthage#tag-stable-releases)。

つまり、バージョン名(=タグ)は下記のような通常のものだけを利用していれば問題ないと思います。
冒頭に `v` などもつける必要はありません。
`1.0.0` `1.0.2` ... `1.1.0` ... `2.0.0` ...



## CocoaPods

### 1. podspec を作成

下記コマンドで `ライブラリ名.podspec` ファイルを生成します。

```sh
pod spec create ライブラリ名
```

作成された下記のようなファイルを、書き換えていきます。
詳細なコメントが書いてあるため、そんなに困らないと思います。
困ったら[公式ページ](https://guides.cocoapods.org/making/specs-and-specs-repo.html)を参考にしてもいいと思います。

```rb:WaveSlider.podspec
Pod::Spec.new do |spec|
  spec.name         = "WaveSlider"
  spec.version      = "1.0.0"
  ...
end
```

下記コマンドで確認し、エラーがなくなるまで修正を繰り返し、 git push します。

```sh
pod spec lint
# もし問題がなければ下記のような出力が表示されるとお見ます
# [ライブラリ名] passed validation.
```

### 2. Release を作成 (タグを付ける)

Release を作成しましょう。
<img width="400" alt="Releaseを作成" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42826/d33ac191-5dec-79d4-549b-94f3bfa3d1b8.png">

### 3. 登録作業

```sh
# 登録
# 確認メールが届くのでリンクを開いて認証する
pod trunk register "メールアドレス" "名前"

# CocoaPods にライブラリの登録
# 場合によっては --allow-warnings オプションを付けてもいいかもしれません
pod trunk push ライブラリ名.podspec
```

これで終わりです！
こんな感じで作成したライブラリのページが作られていると思います！
https://cocoapods.org/pods/WaveSlider

### 4. CI で自動デプロイ



## Carthage

ほぼやることはないです！
基本的に公式ドキュメントもしっかり見れるといいですね。


### 1. 確認作業

下記コマンドを実行して問題ないかを確認します。
成功した際 `Carthage/Build` ディレクトリに成果物ができますが、こちらは git に含める必要はないので `.gitignore` に追記しておくべきです。

```sh
carthage build --no-skip-current

# もし成功しない場合は下記のようなコマンドを実行すると解決の糸口になるかもしれないよ by 公式ドキュメント
xcodebuild -scheme SCHEME -workspace WORKSPACE build
xcodebuild -scheme SCHEME -project PROJECT build
```

### 2. Release を作成 (タグを付ける)

CocoaPods の方の手順と同じです。すでにやっているなら必要ないです。


## Swift Package Manager

Swift Package Manager の対応もしたいですが、時間があるときに気が向いらたらやります。

# 公開の自動化

CocoaPods の `pod trunk push` や、
Carthage のバイナリアップロードなど、
自動化できるところは CI を利用して自動化しましょう。
下記記事で解説してます！

https://qiita.com/yuki0n0/items/b6a954b865c613c9a255

# 参考

- **GitHub**: Carthage Readme<br>
https://github.com/Carthage/Carthage#supporting-carthage-for-your-framework
- **GitHub**: vsouza/awesome-ios<br>
https://github.com/vsouza/awesome-ios
- **Gist**: iOSライブラリの自作とcarthage公開<br>
https://gist.github.com/sahara-ooga/18820c55cc8591694fa7aba651625908
- **Stack Overflow**: What's the difference between 'pod spec lint' and 'pod lib lint'?<br>
https://stackoverflow.com/a/32328089
- **Qiita**: Carthageの配布の仕方（すっごい簡単！）<br>
https://qiita.com/morizotter/items/56658ed7920059beaa8e
- **Qiita**: 自作ライブラリのCocoaPods対応<br>
https://qiita.com/am10/items/9097dd87c4eaa6ec5350
- **teratail**: Carthgeで事前にビルドしたバイナリファイルを提供するには<br>
https://teratail.com/questions/22246