【Swift】お天気アプリを作る(2)気象予報データをテーブルビューで表示しよう

スポンサーリンク
swift Swift(iPhone)

swift

Swiftが3.0になってから初めてのアプリ作成を開始しました。今回のテーマはお天気アプリ。

前回はJSONで出力される天気予報データの取得までを作ったので、今度はデータをUITableViewを使って表示します。

前回の記事は以下になります。

【Swift】お天気アプリを作る(1)JSON形式の気象予報データを取得しよう

前回作ったコードを改造!

画像データも取得する

お天気データをJSON形式で配信してくれる便利なサイト「ライブドア天気情報」。ここから必要そうなデータを取得してくるところまで作りましたが、まずはここを改造して画像データも取得できるようにしておきます。

URLは取得済みなので表示するときに毎回取ってこようと思ったのですが、面倒だったので初期処理の中でやってしまいます。

 

構造体の修正

天気予報データを格納する構造体を作成しましたが、その中にイメージデータを格納する変数を作ります。imgという変数を作成し、データをセットする部分を追加します。

struct Weather {
    var dateLabel: String
    var telop: String
    var date: String
    var minTemperatureCcelsius: String
    var maxTemperatureCcelsius: String
    var url: String
    var img: UIImage
    var title: String
    var width: Int
    var height: Int
    
    init(dateLabel: String, telop: String, date: String, minTemperatureCcelsius: String, maxTemperatureCcelsius: String, url: String, img: UIImage, title: String, width: Int, height: Int) {
        self.dateLabel = dateLabel
        self.telop = telop
        self.date = date
        self.minTemperatureCcelsius = minTemperatureCcelsius
        self.maxTemperatureCcelsius = maxTemperatureCcelsius
        self.url = url
        self.img = img
        self.title = title
        self.width = width
        self.height = height
    }
}

 

データの格納処理も修正します

構造体にデータをセットする部分も影響を受けるので直します。データをセットする前に、URLから画像を取ってきて変数に入れています。weatherにデータを追加する部分の前に下記の1〜3行目を追加して、appendする部分にその変数imgを追記します。

                        let imgUrl = URL(string: url)
                        let imgData = try? Data(contentsOf: imgUrl!)
                        let img = UIImage(data: imgData!)
            
                        weather.append(Weather(dateLabel: dateLabel, telop: telop, date: date, minTemperatureCcelsius: minTemperatureCcelsius, maxTemperatureCcelsius: maxTemperatureCcelsius, url: url, img: img!, title: title, width: width, height: height))

画像データの取り方は同期/非同期などいろいろあるのですが、ここでは以下のリンク先で一番簡単そうな方法を選びました。

Loading/Downloading image from URL on Swift

 

お次はテーブルビューの設定

いよいよデータの準備ができたので、テーブルビューに表示する部分を作っていきます。ほぼ以下の参考サイトそのままの作りです。

[Swift3] UITableViewの基本的な使い方とリスト作成サンプル

途中でいろいろエラーが表示されるかもしれませんが、気にせず一気に行きましょう。

 

テーブルビューの定義

ViewControllerの部分に、テーブルビューを使用するときに必要なデリゲートとデータソースの記述を追加します。ストーリーボードを使わないでテーブルビューを使うためのお約束ですね。

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

 

エラーが出ても気にせずに、続けてviewDidLoadの前にステータスバーの高さを取得する変数とテーブルビューの定義を追加します。画面いっぱいにテーブルビューを表示してしまうと電池や時刻の表示される部分に被ってしまうので、そこを考慮して配置するためにステータスバーの高さを使います。

    let statusBarHeight = UIApplication.shared.statusBarFrame.height
    let tableView = UITableView()

 

次はviewDidLoadの最初にテーブルビューの描画処理を追加します。ここも参考サイトそのままです。ビューのサイズを決定するところで、ステータスバーの高さ分下げた位置から表示させているのがわかると思います。

        // UITableView を作成
        // サイズと位置調整
        tableView.frame = CGRect(
            x: 0,
            y: statusBarHeight,
            width: self.view.frame.width,
            height: self.view.frame.height - statusBarHeight
        )
        
        // Delegate設定
        tableView.delegate = self
        
        // DataSource設定
        tableView.dataSource = self
        
        // 画面に UITableView を追加
        self.view.addSubview(tableView)

 

取ってきたデータをテーブルビューに表示する

先ほど構造体部分を変更したときに、データを格納する処理を変更しましたが、そのすぐ下に以下のコードを追加して、データを取得後、テーブルビューをリロードして再描画する命令を追加します。

                        let imgUrl = URL(string: url)
                        let imgData = try? Data(contentsOf: imgUrl!)
                        let img = UIImage(data: imgData!)
            
                        weather.append(Weather(dateLabel: dateLabel, telop: telop, date: date, minTemperatureCcelsius: minTemperatureCcelsius, maxTemperatureCcelsius: maxTemperatureCcelsius, url: url, img: img!, title: title, width: width, height: height))
                        
                    }
                    DispatchQueue.main.async {
                        self.tableView.reloadData()
                    }

DispatchQueue.main.asyncというのは、メインスレッドでリロード描画処理を実行しますよ、という意味のようで、これがないと起動してから10秒くらい待たないと天気データが表示されません。

viewDidLoad処理の中でreloadDataを実行するときにはこんな風に書いておきましょう。本気でアプリ作るならもっと全体を考えたうえで作ることになると思うので、ご参考程度に。

 

テーブルビューで必要な関数を追加

全く使わないdidReceiveMemoryWarningの下に、以下の関数を追加したら終了です。

    // MARK: - UITableViewDataSource
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = UITableViewCell(style: .subtitle, reuseIdentifier: "cell")
        // セルの中身を設定
        cell.accessoryType = .none
        cell.textLabel?.text = "\(weather[indexPath.row].dateLabel)の天気:\(weather[indexPath.row].telop)"
        cell.detailTextLabel?.text = "最低気温\(weather[indexPath.row].minTemperatureCcelsius)度  最高気温\(weather[indexPath.row].maxTemperatureCcelsius)度"
        cell.imageView!.image = weather[indexPath.row].img
        return cell
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // セルの数を設定
        return weather.count
    }
    
    // MARK: - UITableViewDelegate
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        // セルの高さを設定
        return 64
    }

最初の関数では、テーブルビューのラベルと画像を設定しています。カスタムセルを用意しなくても標準のままでこれくらいならできてしまいます。

2番目の関数はテーブルビューに表示されるデータの個数を返しています。JSONで取得したデータは変数に入っているので、変数に格納されているデータの個数をセットしています。

最後の関数は必須ではないのですが、なんとなくセルの幅が広い方がカッコよかったので64に設定しています。これはお好みで修正してください。

 

これでエラーも表示されなくなったと思いますので実行してみましょう。見た目ショボいですが、ちゃんと天気予報が表示されることを確認してください。画像が追加されるだけでそれなりに見えるような気がします。

 

おわりに

次回で最後になる予定です。まだお天気概況などが表示されていないので、追加して実際に役に立ちそうなアプリに仕上げたいと思います。

今回のサンプルはこちらに置いてあります。

【Swift】お天気アプリを作る(3)セルの高さを可変にしてお天気概況を表示しよう

[amazonjs asin=”4797389818″ locale=”JP” title=”絶対に挫折しない iPhoneアプリ開発「超」入門 増補改訂第5版 【Swift 3 & iOS 10.1以降】 完全対応 (Informatics&IDEA)”]

タイトルとURLをコピーしました