0
1

More than 3 years have passed since last update.

【Swift】API、JSON解析を使う

Last updated at Posted at 2021-02-19

今回はこちら↓で作ったSwift5Boketeアプリの復習
【iOS14対応】未経験者がiPhoneアプリ開発者になるための全て iOS Boot Camp

61dfbaebcff9d63d53eabc251ec044c4.gif

検索欄にキーワードを入力すると、関連する画像が出てきます。
気に入った画像に適当にネタを入れて決定ボタンを押し、シェアするボタンを押すとスクリーンショットが作られ、Twitter等に投稿することができます。

このアプリでは
①ライブラリの導入方法
②APIの使い方
③JSONの使い方
を学びました。

cocoapodsでライブラリを導入する

ライブラリに関しては動画内でもこちらのサイトを参照されていたので、このサイトを参考にするのが良いかと思います。

今回使用するライブラリは

pod 'SwiftyJSON' => JSONを使用するライブラリ
pod 'Alamofire' => ネットワークを使用するライブラリ
pod 'SDwebImage' => URLで引っ張ってきた画像を高速で使用することができるライブラリ

の3つです。
UIは以下の通り。
スクリーンショット 2021-02-19 12.11.18.jpg
画像上に各パーツの名前(インスタンス名)を書いています。

ViewController↑で導入したライブラリを使用するのと、デバイス内のアルバムを使用するために

ViewController.swift
import Alamofire
import SwiftyJSON
import SDWebImage
import Photos

classの前に追記します。

作成したスクリーンショットをアルバムに保存するためのプログラムを、viewDidLoad内に記述します。

viewController.swift
PHPhotoLibrary.requestAuthorization { (status) in
  switch(status){
    case .authorized: break
    case .denied: break
    case .noDetermined: break
    case .restricted: break
    }
}

APIについて

APIはApplication Program Interfaceの略です。
簡単に言うと、とあるサービスがソフトウェアの一部を公開して、他のソフトウェアに機能を使えるようにできます(多分)
公開元が発行しているAPIキーを使い、発行元が公開している仕様書に従ってプログラムを記述することで、自分のソフトウェアに機能を導入することができます。

今回使用するのがpixabeyと言う無償画像提供サイトのAPI。
このAPIを使用して行いたいのは、アプリ内のSearchTextFieldに入力したキーワードで画像をpixabayから引っ張り出してくることです。
流れとしては、https://pixabay.com/api/?key=[個人のAPIキー]&q=[検索ワード]pixabayのサーバーにリクエストを送ると、json形式でレスポンス(検索結果)が返ってくるので、このデータにjson解析を行って画像を引っ張ってきます。

例えば検索ワードをyellow+flowerとした場合、pixabayのレスポンスは以下のような形で返ってきます。
スクリーンショット 2021-02-19 14.05.10.png

プログラムを書きます。
まず、画像のURLを取得するメソッドを作成します。

ViewController.swift
func getImages(keyword:String) {
  //APIを使う
    let url = "https://pixabay.com/api/?key=[個人のAPIキー]&q=\(keyword)"
    //Alamofireを使ってHTTPリクエストを行う
    AF.request(url, method: get, parameters: nil, encoding: JsonEncoding.default).responseJSON{ (response) in //<= クロージャー
      switch response.result{
        case .success: //<=サーバーからリクエストを正常に受け取れたかどうかで条件分岐
    //JSON形式で返ってきたデータにJSON解析を行う
          let json:JSON = JSON(response.date as Any) //<=ここでデータを取得する
    //必要なデータを取り出し変数に格納する
          var imageString = json["hits"][self.count]["webformatURL"].string //<=hitsの配列内にあるwebformatURLをとってくる
          self.odaiImageView.sd_setImage(with: URL(string: imageString!), completed:nil)

        case .failure:
          print(error)
        }
      }
    }

流れをざっくり説明すると...
検索欄に入力されたキーワードが、APIキーと共にパラメーターになってpixabayに送信されます。
すると、上のようなデータがJSON形式と言う形で返ってきます。
そのデータは辞書型で値が入っています。
その中の、hitsというキーが持っている配列の中に、検索ワードと一致する分だけ同じ数の配列が入っています。
各配列の中のwebformatURLを、ViewControllerodaiImageViewに表示させたい、というわけです。

そして次のお題ボタンをタップすると、次の画像が表示されるようにしたいので、nextOdaiという名前でアクションを作成します。

ViewController.swift
@IBAction func nextOdai(_ sender: Any) {
  count += 1 //<= 冒頭でvar count = 0と宣言しておく
  if searchTextField.text == ""{
    getImage(keyword: "funny")
  } else {
    getImage(keyword: searchTextField.text!)
  }
}

countをインクリメントすることで、次のお題ボタンを押すたびにJSON内の配列を順番に参照することができます。

但し、次へボタンを押しまくって、["hits"]内の配列の数よりcountが多くなってしまうと、参照する値がなくなってしまい、エラーになってしまします。これを避けるために、getImagesメソッド内のlet imageString =....stringの行の次に、以下のプログラムを追記します。

ViewController.swift
if imageString == nil {
  imageString = json["hits"][0]["webformatURL"].string
                    //↓これは画像を表示できるようにするために導入したSDWebImageのメソッドです
  self.odaiImageView.sd_setImage(with: URL(string: imageString!), completed: nil)
} else {
  self.odaiImageView.sd_setImage(with: URL(string: imageString!), completed: nil)
}

次に、🔍ボタンを押した時の機能を書きます。

ViewController.swift
@IBAction func searchAction(_ sender: Any) {
  self.count = 0
  if searchTextField.text == "" {
    getImages(keyword: "funny")
  } else {
    getImages(keyword: searchTextField.text!)
  }
}

上との違いはというとself.count = 0ですが、searchActionは検索して一番最初のデータを持ってくるので、count = 0、すなわち["hits"][0]を持ってくる必要があるのでこの記述が必要です。(多分)

次に決定ボタンが押された時の機能を書きます。
決定ボタンが押された時の流れとしては、ViewControllerで選択した画像とコメントを次の画面に遷移して渡す必要があります。
あと、画面間で値を受け渡しするためのprepare for segueも一緒に書きます。

ViewController.swift
@IBAction func done(_sender: Any) {
  performSegue(withIdentifier: "next", sender: nil)
}
override func prepare(for segue: UIStoryBoardSegue, sender: Any?) {
  let shareVC = segue.destination as? ShareViewController
  shareVC?.resultImage = odaiImageView.image!
  shareVC?.commentString = commentTextView.text
}

遷移先のプログラムを書きます。

ShareViewController.swift
var resultImage = UIImage()
var commentsString = String()
var screenShotImage = UIImage()

上の2つの値はViewControllerですでに値を受け取っているので、viewDidLoadメソッド内で

ShareViewController.swift
resultImageView.image = resultImage
commentLabel.text = commentString

と記述して遷移先の画面に値を反映します。

次にスクリーンショットの機能を書きます。
これは何も考えず、こういう風に書くんだな、と思っておくのが良さそうです。

ShareViewController.swift
func takeScreenshot(){
 let width = CGFloat(UIScreen.main.bounds.size.width)
 let height = CGFloat(UIScreen.main.bounds.size.height/1.3)
 let size = CGSize(width: width, height: height)

 UIGraphicsBeginImageContextWithOptions(size, false, 0.0)

 self.view.drawHierarchy(in: view.bounds, afterScreenUpdates: true)
 screenShotImage = UIGraphicsGetImageFromCurrentImageContext()!
 UIGraphicsEndImageContext()
}

そして、共有ボタンを押したらスクリーンショットが発動して共有できるようにしたいので、↑のメソッドを利用して、

ShareViewController.swift
@IBAction func share(_ sender: Any) {
  //スクリーンショットを撮る
  takeScreenshot()

  let items = [screenShotImage] as [Any]
 //アクティビティビューに乗っけてシェアする
  let activityView = UIActivityViewController(activityItems: items, applicationActivities: nil)
  present(activityView, animated: true, completion: nil)
}

これで一通り完成です。

感想

Ruby on Railsでもいくつかライブラリ使用しましたが、Swiftのもあるんですね(あほ)。
!だったり?だったりself書いたりって細かい違いのところがまだ把握できてないので、今後の学習の中でつかんでいきたいと思います。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1