今回はこちら↓で作ったSwift5Boketeアプリの復習
【iOS14対応】未経験者がiPhoneアプリ開発者になるための全て iOS Boot Camp
検索欄にキーワードを入力すると、関連する画像が出てきます。
気に入った画像に適当にネタを入れて決定ボタンを押し、シェアするボタンを押すとスクリーンショットが作られ、Twitter等に投稿することができます。
このアプリでは
①ライブラリの導入方法
②APIの使い方
③JSONの使い方
を学びました。
cocoapodsでライブラリを導入する
ライブラリに関しては動画内でも[こちら]('こちら' https://qiita.com/ShinokiRyosei/items/3090290cb72434852460)のサイトを参照されていたので、このサイトを参考にするのが良いかと思います。
今回使用するライブラリは
pod 'SwiftyJSON' => JSONを使用するライブラリ
pod 'Alamofire' => ネットワークを使用するライブラリ
pod 'SDwebImage' => URLで引っ張ってきた画像を高速で使用することができるライブラリ
の3つです。
UIは以下の通り。

画像上に各パーツの名前(インスタンス名)を書いています。
ViewController↑で導入したライブラリを使用するのと、デバイス内のアルバムを使用するために
import Alamofire
import SwiftyJSON
import SDWebImage
import Photos
をclassの前に追記します。
作成したスクリーンショットをアルバムに保存するためのプログラムを、viewDidLoad内に記述します。
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]('pixabay' https://pixabay.com/ja/service/about/api/)と言う無償画像提供サイトのAPI。
このAPIを使用して行いたいのは、アプリ内のSearchTextFieldに入力したキーワードで画像をpixabayから引っ張り出してくることです。
流れとしては、https://pixabay.com/api/?key=[個人のAPIキー]&q=[検索ワード]でpixabayのサーバーにリクエストを送ると、json形式でレスポンス(検索結果)が返ってくるので、このデータにjson解析を行って画像を引っ張ってきます。
例えば検索ワードをyellow+flowerとした場合、pixabayのレスポンスは以下のような形で返ってきます。

プログラムを書きます。
まず、画像のURLを取得するメソッドを作成します。
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を、ViewControllerのodaiImageViewに表示させたい、というわけです。
そして次のお題ボタンをタップすると、次の画像が表示されるようにしたいので、nextOdaiという名前でアクションを作成します。
@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の行の次に、以下のプログラムを追記します。
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)
}
次に、🔍ボタンを押した時の機能を書きます。
@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も一緒に書きます。
@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
}
遷移先のプログラムを書きます。
var resultImage = UIImage()
var commentsString = String()
var screenShotImage = UIImage()
上の2つの値はViewControllerですでに値を受け取っているので、viewDidLoadメソッド内で
resultImageView.image = resultImage
commentLabel.text = commentString
と記述して遷移先の画面に値を反映します。
次にスクリーンショットの機能を書きます。
これは何も考えず、こういう風に書くんだな、と思っておくのが良さそうです。
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()
}
そして、共有ボタンを押したらスクリーンショットが発動して共有できるようにしたいので、↑のメソッドを利用して、
@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書いたりって細かい違いのところがまだ把握できてないので、今後の学習の中でつかんでいきたいと思います。
