kudokai’s diary

自由気ままに書いていきます

非同期処理と出会った話 ー前編ー

コロナウイルスの影響で春休みが伸びたので、swiftでAPIを使ったお菓子検索アプリを作ってみることにしました。このアプリは入門書でURLSessionで書かれていますが、僕が勝手にリファクタしました。

ライブラリはAlamofireを使っています。

github.com

 

ここから先はコードの一部分を載せていきます。全部載せると長くなり、読みにくいと思うので。。。

分かりにくいとは思いますが、ご容赦願います。<(_ _)>

 

一応、完成版はこちらです⬇️。

github.com

 

    • 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だったのか全く見当がつかなかったです。

 

 非同期処理を記述して解決するのですが、次回に詳しいことを書こうと思います。