[Swift]Google Places API の結果を TableView に反映させる

2019年4月2日ITSwift

こんにちは、ハラダ(@nobuhiro_harada)です

Google Places API を叩いて、取得結果を TableView に反映させてみました

APIキーの取得の仕方は公式サイトがわかりやすかったです

参考:Google Places API Web Service のキーを取得する

レイアウト

・Main.storyboard
検索バーを TextField、その下に TableView を配置してます
TableView の中に TableViewCell を置き、UILabel を1つだけ載せています
places-api-tableview1.png

・TextField(検索バー) ※下記のみ変更

places-api-tableview2.png

Correction (自動補正):NO
Spell Checking (スペルチェック):NO
Return Key:Search
参考:Apple公式ドキュメントUITextField

・TableView のセルの ID は”placecell” に設定

places-api-tableview3.png

・TableView 内のUILabelのタグは “102” に設定

places-api-tableview4.png

ViewController.swift 中身

import UIKit

class ViewController: UIViewController, UITextFieldDelegate, UITableViewDataSource, UITableViewDelegate {

    @IBOutlet weak var searchTextField: UITextField!
    @IBOutlet weak var placesTable: UITableView!
    
    // Google Places API の取得結果はDictionary型で返ってくる
    var resultsArray:[Dictionary<String, AnyObject>] = Array()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        searchTextField.delegate = self
        placesTable.dataSource = self
        placesTable.delegate = self
    }

    // MARK: - UITableViewDataSource and UITableViewDelegate
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return resultsArray.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "placecell")
        
        if let placeLabel = cell?.contentView.viewWithTag(102) as? UILabel {
            let place = self.resultsArray[indexPath.row]
            placeLabel.text = "\(place["name"] as! String) \(place["formatted_address"] as! String)"
        }
        
        return cell!
    }
    
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: true)
        
        let place = self.resultsArray[indexPath.row]
        if let geometry = place["geometry"] as? Dictionary<String, AnyObject> {
            if let location = geometry["location"] as? Dictionary<String, AnyObject> {
                UIApplication.shared.open(URL(string: "https://www.google.com/maps/@\(location["lat"]!),\(location["lng"]!),16z")!, options: [:])
            }
        }
    }
    
    // MARK: -UITextFieldDelegate
    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        searchGooglePlaces(place: textField.text!)
        return true
    }
    
    func searchGooglePlaces(place: String) {
        var strGoogleApi = "https://maps.googleapis.com/maps/api/place/textsearch/json?query=\(place)&language=ja&key=[YOUR API KEY]"
        strGoogleApi = strGoogleApi.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!
        
        var urlRequest = URLRequest(url: URL(string: strGoogleApi)!)
        urlRequest.httpMethod = "GET"
        
        let task = URLSession.shared.dataTask(with: urlRequest) {
            (data, response, error) in
            if error == nil {
                let jsonDict = try? JSONSerialization.jsonObject(with: data!, options: .mutableContainers)
                
                if let dict = jsonDict as? Dictionary<String, AnyObject> {
                    if let results = dict["results"] as? [Dictionary<String, AnyObject>] {
                        
                        self.resultsArray.removeAll()
                        for result in results {
                            self.resultsArray.append(result)
                        }
                        
                        DispatchQueue.main.async {
                            self.placesTable.reloadData()
                        }
                    }
                }
                
            } else {
                
            }
        }
        task.resume()
    }

}

API 取得結果例

[["geometry": {
    location =     {
        lat = "35.7090259";
        lng = "139.7319925";
    };
    viewport =     {
        northeast =         {
            lat = "35.8175167";
            lng = "139.9198565";
        };
        southwest =         {
            lat = "35.5208603";
            lng = "139.5629048";
        };
    };
}, "name": 東京, "reference": CmRbAAAAhBwPHusw8DCUp6u9NQigen5ue3zfWGXHs-t4kgQ2meuuu4YTMmCrdxSFvhC4P1zIpEaMpXe7tBkldhtSgmPap0burMljries8Rtkco2R3VElH3dEEf-re_miq4BDAic_EhAJP3tzRW92QL8UEfSsQ4FCGhTwQIMJ3D1IM9XyQC5PxlJ4PX9bkg, "icon": https://maps.gstatic.com/mapfiles/place_api/icons/geocode-71.png, "id": 45c0b5209973fcec652817e16e20f1d0b4ecb602, "place_id": ChIJXSModoWLGGARILWiCfeu2M0, "formatted_address": 日本、東京都, "photos": <__NSArrayM 0x60000024c030>(
{
    height = 768;
    "html_attributions" =     (
        "<a href=\"https://maps.google.com/maps/contrib/113662527701653401777/photos\">T. Seemann</a>"
    );
    "photo_reference" = "CmRaAAAAICg6Vb1Wj4ozrAc_N770uhqShEeDuQatzbSnXZ3qo7asUebSOXzQSwL9bdhfxf8AuR6VQQcjUmfELoy4Dgxd9YPGcGuqKrAqkENRfV6XlePZTPYr3OV4Rs3HEGwiKjt5EhDUu_KQxH9o8ybG4qenqGV5GhSycdRnfTOPlgJnGIhyytmZksKmGA";
    width = 1024;
}
)
, "types": <__NSArrayM 0x60000024ab60>(
colloquial_area,
locality,
political
)
]]

結果

以上になります

ひとこと

APIの取得結果が Dictionary型で String、AnyObject で返ってくるのですが、どう受けてやるのが1番清く、正しく、美しいのか、、、

スポンサーリンク

Posted by nobuhiro harada