【Swift,iOS】いい感じのアドバイスをくれるアプリを作ってみた

# やりたいこと
* いい感じのアドバイスをくれるAPIを使って、いい感じのアドバイスを画面に表示させたい

    1\. Advice Slip JSON API というものを使っていい感じのアドバイスを英語で取得
    2\. 取得した英語のアドバイスをDeepLのAPIを使って翻訳
    3\. 画面に表示
    この流れでやっていきます。

## 完成図
<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1070398/4b9f4a2d-3883-8f3f-ade6-5d3764686277.png">

画面をタップするとアドバイスが更新されます。

## やってみる

https://api.adviceslip.com/advice

<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1070398/38d572b5-a020-912d-cdcf-0640cf21d287.png">

アドバイスのURLにアクセスすると、このようなJSONが帰ってくるので、それに対応した構造体を作ります。

```swift:AdviceData.swift
import Foundation

struct AdviceData: Decodable {
    let slip: Advice
}

struct Advice: Decodable {
    let advice: String
}
```

次に、URLにアクセスし、帰ってきたJSONをデコードします。
```swift
func fetchAdviceData() {
    
    if let url = URL(string: self.adviceUrlString) {
        let session = URLSession(configuration: .default)
        let task = session.dataTask(with: url) { data, response, error in
            if let error = error {
                print(error)
            }
            
            if let safeData = data {
                let decoder = JSONDecoder()
                do {
                    let decodeData = try decoder.decode(AdviceData.self, from: safeData)
                    let advice = decodeData.slip.advice
                    delegate?.didUpdateAdvice(self, advice: advice)
                } catch {
                    delegate?.didFailWithError(error: error)
                }
            }
        }
        task.resume()
}
```
そして取得したアドバイスをDeepLのAPIに投げて翻訳してもらいます。

```swift
    func translate(advice: String) {
         
        let parameters: [String: String] = [
            "text": advice,
            "target_lang": "JA",
            "auth_key": authKey
        ]
        
        let headers: HTTPHeaders = [
            "Content-Type": "application/x-www-form-urlencoded"
        ]

        let decoder = JSONDecoder()
        AF.request("https://api-free.deepl.com/v2/translate", method: .post, parameters: parameters, encoder: URLEncodedFormParameterEncoder.default, headers: headers).responseDecodable(of: DeepLResult.self, decoder: decoder) { response in
            
            if case .success = response.result {
                do {
                    let result = try decoder.decode(DeepLResult.self, from: response.data!)
                    let  translatedText =  result.translations[0].text
                    delegate?.adviceDidTranslate(advice: translatedText)
                } catch {
                    debugPrint("デコード失敗")
                }
            } else {
                debugPrint("APIリクエストエラー, \(response.error)")
            }
        }
        
    }
```



これで翻訳されたアドバイスが取得できるので、あとはラベルに表示するだけですが
名言ぽくしたかったのでCLTypingLabelというライブラリを使ってみました。
ラベルにテキストを設定するだけなので簡単に使えます。
一文字ずつ文字が入力されていくアニメーションが名言らしい雰囲気を出してくれます。



https://qiita.com/goofmint/items/73c96af20c1963bc8fee

今回はこの記事を参考にしました。
ただ記事の通りに実装してもDeepLのAPIを使うときに、Alamofireでエラーが出てしまいます。

```swift
responseDecodable(of: DeepLResult.self)
```
この部分を
```swift
responseDecodable(of: DeepLResult.self, decoder: decoder)
```
このように修正してあげるとうまくいきました。詳しくは上のコードを見てみてください。

Githubに上げてみました。

https://github.com/hidey7/goodAdiviceApp