【Swift】フォーム作成ライブラリ「Eureka」で投稿フォームを作る

#概要
UITableViewはアプリを作る上で基本となり、欠かせない部分です。
実際に世の中にあるアプリのほとんどが使用されています。

しかし、いざ作るとなったらいろいろめんどくさいのも事実です。
できれば楽に綺麗に作成したいですよね、、、。
そんな、UITableViewのめんどくさい部分を「綺麗に」「簡単に」克服できるライブラリがありましたので書き残しておきます。
それが[Eureka](https://github.com/xmartlabs/Eureka)です。
#完成予想図
今回は、サンプルとしてEurekaを用いた投稿フォームを作成しました。
実際に、投稿ボタンを押すとmBaaS(mobile backend as a Service)というクラウドサービスに保存されるまでをご紹介します。
![result2](https://user-images.githubusercontent.com/64241438/106362209-f7c9a980-6364-11eb-8ef5-385b7e361408.gif)
今回用いた機能がEurekaの全てではないので、もっといろんな機能を使ってみたい方はこちらの[Github](https://github.com/xmartlabs/Eureka)からいろいろ探してみてください！
#Eurekaとは
Eurekaはウルグアイのアプリデザイン会社XMARTLABSが開発をしているオープンソースです。
もともと「XLForm」というフォーム作成用ライブラリを提供しており、それをSwiftで作り直したものになります。
#インストール
インストール方法は、CocoaPods、Carthageを使う方法などがあります。今回はCocoaPodsでインストールを行います。

Podfileを作成し、そのPodfileに

```
pod 'Eureka'
```
と記入して、`pod install`するだけでインストールできます。
#ViewControllerの作成
storyboardにUIパーツなどを置く必要はありません。
その代わりに1つ注意することが`FormViewController`を継承したサブクラスを作成する必要があります。
今回は下にある通り、`UIViewContoroller`→`FormViewController`と変換しました。

```swift

import Eureka

class ViewController: FormViewController {
    
    override func viewDidLoad() {
            super.viewDidLoad()
    }

}
```
これで、投稿フォームを作る準備は整いました。
このクラスは`form`というフォームのプロパティを持ちます。
次は、`form`プロパティに特殊なオペレーターを使うことでフォームに、セクションやセルを追加していきます。

#オペレーター
実際にフォームのパーツを作るコードを書いていきます。
初見では、今まで見たことないようなコードにぎょっとしてしまいますが落ち着いて書いていきましょう。案外慣れます。
###+++
`+++`はformプロパティにセクションを追加するオペレーターです。
コードは`viewDidLoad()`内に書きます。

```swift
    override func viewDidLoad() {
        super.viewDidLoad()

        form +++ Section("セクション1")
    
    }
```
こちらのコードを追加すると以下のように表示されます。
<img src="https://user-images.githubusercontent.com/64241438/106360164-5178a680-635a-11eb-9f0a-70b1a173315c.png" width="250">
薄く上の方に「セクション1」と書かれているのが分かると思います。
これでセクションの追加ができました。

###<<<
`<<<`はセルをセクションに追加するオペレーターです。
先ほどのコードにこのセルを追加するコードを描きます。

```swift

    override func viewDidLoad() {
        super.viewDidLoad()

        form +++ Section("セクション1")
        
        <<< TextRow("タイトル"){ row in
            row.title = "タイトル"
            row.placeholder = "タイトルを入力してね"
        }

    }
```
こちらのコードを追加すると以下のように表示されます。
<img src="https://user-images.githubusercontent.com/64241438/106360436-c1d3f780-635b-11eb-9f74-621f6411cfdd.png" width="250">
これで、SectionとRowの追加ができました。これが基本形になります。
Rowには様々な種類があるので他のも気になる方は[Row一覧](https://github.com/xmartlabs/Eureka#row-catalog)で見てみてください。

#コールバック関数
セルのイベントを検知して処理ができるコールバック関数も多数定義されています。
気になる方は[コールバック関数一覧](https://github.com/xmartlabs/Eureka#callbacks-list)で確認してみてください。

今回の投稿フォームではセルの値が変わった時に呼ばれる`onChange()`を使って、書いた内容を`UserDefaults`に保存していきたいと思います。

```swift

    var userDefault = UserDefaults.standard
    
    override func viewDidLoad() {
        super.viewDidLoad()

        form +++ Section("セクション1")
        
        <<< TextRow("タイトル"){ row in
            row.title = "タイトル"
            row.placeholder = "タイトルを入力してね"
        }.onChange{row in
            self.userDefault.setValue(row.value, forKey: "Title")
        }

    }
```
#作成した投稿フォームのコード
基本的な内容は以上になるので最後に今回の投稿フォームのコードを載せておきます。

```swift

import Eureka
import NCMB
class ViewController: FormViewController {
    
    var userDefault = UserDefaults.standard
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        form +++ Section("セクション1")
            
            <<< TextRow("タイトル"){ row in
                row.title = "タイトル"
                row.placeholder = "タイトルを入力してね"
            }.onChange{row in
                self.userDefault.setValue(row.value, forKey: "Title")
            }
            
            <<< TextAreaRow("メモ"){ row in
                row.title = "メモ"
                row.placeholder = "メモを書いてください。"
            }.onChange{row in
                self.userDefault.setValue(row.value, forKey: "Memo")
            }
            
            +++ Section("セクション2")
            <<< DateRow("Date"){
                $0.title = "日付"
                $0.value = Date(timeIntervalSinceReferenceDate: 0)
            }.onChange({ [unowned self] row in
                self.userDefault.setValue(row.value, forKey: "Date")
            })
            
            +++ Section("レビュー")
            <<< PickerInlineRow<String>() { row in
                row.title = "レビュー"
                row.options = ["★","★★","★★★","★★★★","★★★★★"]
                row.value = row.options.first
            }.onChange {[unowned self] row in
                self.userDefault.setValue(row.value, forKey: "Satisfaction")
            }
            
            +++ Section("")
            <<< ButtonRow("フォーム") {row in
                row.title = "完了"
                row.onCellSelection{[unowned self] ButtonCellOf, row in
                    let object = NCMBObject(className: "Post")
                    object?.setObject(NCMBUser.current(), forKey: "user")
                    object?.setObject(self.userDefault.string(forKey: "Title"), forKey: "Title")
                    object?.setObject(self.userDefault.string(forKey: "Memo"), forKey: "Memo")
                    object?.setObject(self.userDefault.object(forKey: "Date")as! Date, forKey: "Date")
                    object?.setObject(self.userDefault.string(forKey: "Satisfaction"), forKey: "Satisfaction")
                    object?.saveInBackground({ (error) in
                        if error != nil{
                            print(error)
                        } else {
                            let alertController = UIAlertController(title: "投稿完了", message: "内容が投稿されました", preferredStyle: .alert)
                            let action = UIAlertAction(title: "確認", style: .default) { (action) in
                                self.navigationController?.popViewController(animated: true)
                            }
                            alertController.addAction(action)
                            self.present(alertController, animated: true, completion: nil)
                            
                        }
                    })
                    self.userDefault.removeAll()

                }
        }
        
    }
}

extension UserDefaults {
    func removeAll() {
        dictionaryRepresentation().forEach { removeObject(forKey: $0.key) }
    }
}

```
今回は初心者ながらに考えて、`UserDefaults`を用いましたがもっと他にいい方法があるという方はコメントで教えて頂けると有り難いです。

<img src="https://user-images.githubusercontent.com/64241438/106361464-58ef7e00-6361-11eb-8d36-c9e4e5f075f0.png" width="1000">
サーバーにもしっかり保存されていることが確認できました。


#最後に
今回紹介したのは基本的な投稿フォームの作成だけですがEurekaをもっと使ってみると↓みたいのや
![Eureka.gif](https://raw.githubusercontent.com/xmartlabs/Eureka/master/Example/Media/EurekaNavigation.gif)

↓みたいのも
<img src="https://raw.githubusercontent.com/xmartlabs/Eureka/master/Example/Media/EurekaExample2.gif" width="350">
(Eurekaのgithubより)

いろいろできるのでカスタマイズの幅がとても広いと思います。
気になった方はぜひ使ってみてください。

##参考記事
[Swiftで入力フォームが簡単に作れる「Eureka」の使い方](https://qiita.com/wadaaaan/items/6538584816ef44690b5c#%E5%80%A4%E3%81%AE%E5%8F%96%E5%BE%97)
[[Swift]作業効率10倍アップ？フォーム作成ライブラリー「Eureka」チュートリアル](https://blog.personal-factory.com/2015/12/29/eureka-tutorial/)