CocoaPods導入からRxSwift導入まで

# はじめに
Android開発者の私、 @ke__kyukyun1828 ですが、軽量DDDを実践するに当たり、今回レイヤー化アーキテクチャをAndroid, iOSに布教しています。

そして、iOSチームについては、**今Swiftに移行するタイミング**であり、かつ、Androidチームは**ようやくRxJavaを導入するタイミング**であったため、RxSwift導入を検討しました。
*（まだkotlinじゃねぇのです・・）*

ので、今回はRxSwift導入を一度個人開発でも行ってみて、知見を共有できればと思います。

# 注意事項
一点、この記事の注意事項として、私はAndroidエンジニアとしてご飯を食べているので、
iOSについての記事は今回が初めてなので、至らないところが多々あると思います。
ので、その場合は指摘をたくさんしていただければと思います。

# アジェンダ
この記事は
1. CocoaPodsの導入
2. Podfileの生成
3. RxSwiftのインストール
4. コードの記述
となります。
では、はじめましょう！

## CocoaPodsの導入
まずはCocoaPodsの導入からです。

### CocoaPodsインストール
以下のコマンドをターミナルで叩きましょう

```
$ sudo gem install cocoapods
```

#### なんかエラーが出た
素直に上のコマンドを叩いてみたところ、以下のエラーが出ました。

```
$ sudo gem install cocoapods
Password:
Fetching: thread_safe-0.3.6.gem (100%)
Successfully installed thread_safe-0.3.6
Fetching: tzinfo-1.2.7.gem (100%)
Successfully installed tzinfo-1.2.7
Fetching: concurrent-ruby-1.1.6.gem (100%)
Successfully installed concurrent-ruby-1.1.6
Fetching: i18n-0.9.5.gem (100%)
Successfully installed i18n-0.9.5
Fetching: activesupport-4.2.11.1.gem (100%)
Successfully installed activesupport-4.2.11.1
Fetching: nap-1.1.0.gem (100%)
Successfully installed nap-1.1.0
Fetching: fuzzy_match-2.0.4.gem (100%)
Successfully installed fuzzy_match-2.0.4
Fetching: httpclient-2.8.3.gem (100%)
Successfully installed httpclient-2.8.3
Fetching: algoliasearch-1.27.1.gem (100%)
Successfully installed algoliasearch-1.27.1
Fetching: ffi-1.12.2.gem (100%)
Building native extensions.  This could take a while...
ERROR:  Error installing cocoapods:
	ERROR: Failed to build gem native extension.

    current directory: /Library/Ruby/Gems/2.3.0/gems/ffi-1.12.2/ext/ffi_c
/System/Library/Frameworks/Ruby.framework/Versions/2.3/usr/bin/ruby -r ./siteconf20200407-12473-17rg51j.rb extconf.rb
checking for ffi.h... *** extconf.rb failed ***
Could not create Makefile due to some reason, probably lack of necessary
libraries and/or headers.  Check the mkmf.log file for more details.  You may
need configuration options.

Provided configuration options:
	--with-opt-dir
	--without-opt-dir
	--with-opt-include
	--without-opt-include=${opt-dir}/include
	--with-opt-lib
	--without-opt-lib=${opt-dir}/lib
	--with-make-prog
	--without-make-prog
	--srcdir=.
	--curdir
	--ruby=/System/Library/Frameworks/Ruby.framework/Versions/2.3/usr/bin/$(RUBY_BASE_NAME)
	--with-ffi_c-dir
	--without-ffi_c-dir
	--with-ffi_c-include
	--without-ffi_c-include=${ffi_c-dir}/include
	--with-ffi_c-lib
	--without-ffi_c-lib=${ffi_c-dir}/lib
	--enable-system-libffi
	--disable-system-libffi
	--with-libffi-config
	--without-libffi-config
	--with-pkg-config
	--without-pkg-config
/System/Library/Frameworks/Ruby.framework/Versions/2.3/usr/lib/ruby/2.3.0/mkmf.rb:456:in `try_do': The compiler failed to generate an executable file. (RuntimeError)
You have to install development tools first.
	from /System/Library/Frameworks/Ruby.framework/Versions/2.3/usr/lib/ruby/2.3.0/mkmf.rb:571:in `block in try_compile'
	from /System/Library/Frameworks/Ruby.framework/Versions/2.3/usr/lib/ruby/2.3.0/mkmf.rb:524:in `with_werror'
	from /System/Library/Frameworks/Ruby.framework/Versions/2.3/usr/lib/ruby/2.3.0/mkmf.rb:571:in `try_compile'
	from /System/Library/Frameworks/Ruby.framework/Versions/2.3/usr/lib/ruby/2.3.0/mkmf.rb:1091:in `block in have_header'
	from /System/Library/Frameworks/Ruby.framework/Versions/2.3/usr/lib/ruby/2.3.0/mkmf.rb:942:in `block in checking_for'
	from /System/Library/Frameworks/Ruby.framework/Versions/2.3/usr/lib/ruby/2.3.0/mkmf.rb:350:in `block (2 levels) in postpone'
	from /System/Library/Frameworks/Ruby.framework/Versions/2.3/usr/lib/ruby/2.3.0/mkmf.rb:320:in `open'
	from /System/Library/Frameworks/Ruby.framework/Versions/2.3/usr/lib/ruby/2.3.0/mkmf.rb:350:in `block in postpone'
	from /System/Library/Frameworks/Ruby.framework/Versions/2.3/usr/lib/ruby/2.3.0/mkmf.rb:320:in `open'
	from /System/Library/Frameworks/Ruby.framework/Versions/2.3/usr/lib/ruby/2.3.0/mkmf.rb:346:in `postpone'
	from /System/Library/Frameworks/Ruby.framework/Versions/2.3/usr/lib/ruby/2.3.0/mkmf.rb:941:in `checking_for'
	from /System/Library/Frameworks/Ruby.framework/Versions/2.3/usr/lib/ruby/2.3.0/mkmf.rb:1090:in `have_header'
	from extconf.rb:10:in `system_libffi_usable?'
	from extconf.rb:34:in `<main>'

To see why this extension failed to compile, please check the mkmf.log which can be found here:

  /Library/Ruby/Gems/2.3.0/extensions/universal-darwin-18/2.3.0/ffi-1.12.2/mkmf.log

extconf failed, exit code 1

Gem files will remain installed in /Library/Ruby/Gems/2.3.0/gems/ffi-1.12.2 for inspection.
Results logged to /Library/Ruby/Gems/2.3.0/extensions/universal-darwin-18/2.3.0/ffi-1.12.2/gem_make.out
```

なんだろうとググってみたところ、同じような現象の人がいたようです。
https://github.com/CocoaPods/CocoaPods/issues/9568

macOSがMojaveの人は、どうやら最新のCocoaPodsが取得できないようなので、バージョンを指定する必要があるとのこと。

Mojave環境の人は以下のコマンドを打ちましょう。

```
$ sudo gem install cocoapods -v 1.8.4
```

### Podセットアップ
無事にインストールができたら、以下のコマンドを打ちましょう。

```
$ pod setup
```

これでCocoaPodsの導入は完了です。

## プロジェクトにPodfileを作成する
CocoaPodsがインストールできたので、次にライブラリを導入したいプロジェクトに、
Podfileを作成する必要があります。

でははじめます。
### 対象のプロジェクトに移動
ターミナルから、ライブラリを導入したいプロジェクトに移動します。

### Podfileの作成
プロジェクトに移動後、以下のコマンドを打ちます。

```
$ pod init
```
これでPodfileが生成されます。
確認してみましょう。

```
$ ls -la
total 16
drwxr-xr-x   9 murakamikei  staff  288  4  7 16:29 .
drwxr-xr-x   5 murakamikei  staff  160  4  5 17:14 ..
drwxr-xr-x  13 murakamikei  staff  416  4  5 17:18 .git
drwxr-xr-x   8 murakamikei  staff  256  4  5 17:14 FamilyApp
drwxr-xr-x@  5 murakamikei  staff  160  4  5 17:14 FamilyApp.xcodeproj
drwxr-xr-x   4 murakamikei  staff  128  4  5 17:14 FamilyAppTests
drwxr-xr-x   4 murakamikei  staff  128  4  5 17:14 FamilyAppUITests
-rw-r--r--   1 murakamikei  staff  381  4  7 16:29 Podfile
-rw-r--r--   1 murakamikei  staff   17  4  5 17:16 README.md
```
下から2番目にPodfileが生成されていますね。
これで準備はOKです。

vimで開いてみましょう。

```
# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0'

target 'アプリ名' do
  # Comment the next line if you don't want to use dynamic frameworks
  use_frameworks!

  # Pods for アプリ名

  target 'アプリ名Tests' do
    inherit! :search_paths
    # Pods for testing
  end

  target 'アプリ名UITests' do
    # Pods for testing
  end

end
```
Podfileがinitで生成された場合は初期状態がこの状態になります。

これでPodfileの生成は完了です。

### Objective-CからPodfileをupdate利用する人の注意事項
Podfileは、swiftプロジェクトから生成した場合は、use_frameworks!がコメントアウトしていません。

```
target 'FamilyApp' do
  # Comment the next line if you don't want to use dynamic frameworks
  use_frameworks! ←ココ
```
しかし、Objective-Cプロジェクトから生成した場合、use_framework!がコメントアウトしています。

```
target 'FamilyApp' do
  # Comment the next line if you don't want to use dynamic frameworks
  # use_frameworks! ←ココ
```

そのため、**Objective-CからSwiftに移行するタイミング**で、Swift用のライブラリを導入する場合は、まずは**use_framework!のコメントアウトを外すようにしましょう。**
私はこれにハマってしまいました。

## RxSwiftのインストール
では、つぎにRxSwiftをインストールし、プロジェクトに導入します。

### Podfileに記載する
先程のPodfileに以下のように追加します。

```
target 'FamilyApp' do
  # Comment the next line if you don't want to use dynamic frameworks
  use_frameworks!

  # Pods for FamilyApp
  pod 'RxSwift' ← これ
  pod 'RxCocoa' ← 今回は一応これも入れておく
end
```

### ライブラリのインストール
では、Podfileに記載したライブラリをインストールします。

#### はじめてPodfileを導入した場合
以下のコマンドを打ちます。

```
$ pod install
```

#### すでにPodfileがある場合
以下のコマンドを打ちます。

```
$ pod update
```

### インストールの完了
インストールが完了した場合、以下のメッセージが表示されます。

```
Pod installation complete!
```

対象のプロジェクトがxcodeで開いている場合だとインストールが完了せず、以下のようなメッセージが出てしまいます。

```
[!] Please close any current Xcode sessions and use `アプリ名.xcworkspace` for this project from now on.
```

エラーが出ずに`Complete!`と出たなら完了です。

## コードの記述
最後に、RxSwiftをimportして、実際に書いてみましょう！！！

と、したいですが、OSアップデートの影響でxcodeを現在ダウンロード中のため、コード記述は後ほど更新します。

# 参考文献
https://qiita.com/ShinokiRyosei/items/3090290cb72434852460