非同期処理と出会った話 ー前編ー
コロナウイルスの影響で春休みが伸びたので、swiftでAPIを使ったお菓子検索アプリを作ってみることにしました。このアプリは入門書でURLSessionで書かれていますが、僕が勝手にリファクタしました。
ライブラリはAlamofireを使っています。
ここから先はコードの一部分を載せていきます。全部載せると長くなり、読みにくいと思うので。。。
分かりにくいとは思いますが、ご容赦願います。<(_ _)>
一応、完成版はこちらです⬇️。
- RequestOkashi.swift
class RequestOkashi{
var okashiList : [(name:String, maker:String, link:URL, image:URL)] = []
// 引数keywordはUISearchBarに入力する検索したいキーワード
func searchOkashi(keyword : String){
// 全角文字をエンコードやリクエストURLの生成は省略
AF.request(requestURL, method: .get, encoding: JSONEncoding.default).response { response in
switch response.result {
case .success( _):
guard let data = response.data else {return}
let decoder = JSONDecoder()
guard let okashi = try? decoder.decode(ResultJson.self, from: data) else {
return
}
guard let items = okashi.item else {
return
}
self.okashiList.removeAll()
for item in items {
guard let name:String = item.name, let maker:String = item.maker, let link:URL = item.url, let image = item.image else {
return
}
let okashiTuple = (name, maker, link, image)
self.okashiList.append(okashiTuple)
}
case .failure(let error):
print(error)
}
}
}
}
RequestOkashi.swiftではUISearchBarに入力されたお菓子のキーワードを基にリクエストURLを生成して、通信を行っています。通信が成功した場合には、返ってきたJSONをパースしてから、okashiListというタプル配列にお菓子の名前・メーカー・詳細ページURL・画像URLを格納しています。
- ViewController.swift
class ViewController: UIViewController, UISearchBarDelegate, UITableViewDataSource, UITableViewDelegate{
var request = RequestOkashi()
//viewDidLoad()とか省略
// 検索ボタンクリック時に呼ばれるdelegateメソッド
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
view.endEditing(true)
request.searchOkashi(keyword: searchWord)
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
print(self.okashiList.count)
return request.okashiList.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "okashiCell", for: indexPath)
cell.textLabel?.text = request.okashiList[indexPath.row].name
return cell
}
}
ViewController.swiftではUISearchBarへの入力を受けてRequestOkashi.swiftのsearchOkashi()メソッドを呼んでいます。searchOkashi()の処理をもとにtableViewに反映しています。
いざSimulatorを動かすと。。。。
cell.textLabel?.text = request.okashiList[indexPath.row].name
のところでアプリがクラッシュしたり、
print(self.okashiList.count)
のところでnilが表示されたりと、まあめちゃくちゃでした。。。
ここから数日間は上記の問題にずっと悩まされました。
このときの僕は、なぜokashiList.countがnilだったのか全く見当がつかなかったです。
非同期処理を記述して解決するのですが、次回に詳しいことを書こうと思います。