Help us understand the problem. What is going on with this article?

SwiftでconnpassAPIを叩いて記事を取得してみた

More than 1 year has passed since last update.

はじめに

オイシックス・ラ・大地(以下オイラ大地)の新卒エンジニアの城間です。
この記事はオイラ大地株式会社アドベントカレンダーの19日目の記事になります。
Oisix ra daichi Inc. Advent Calendar 2018

11月からiosエンジニアとして所属しており、本記事では課題として作ったアプリを
書いていきたいと思います。
Swiftは初学者で色々とつまづいていたので、参考になれば幸いです。

使用したAPI

connpass APIを使用しました。(https://connpass.com/about/api/)
レスポンスフィールドとしては下記を取得します。

フィールド 説明
events 配列(複数要素) 検索結果のイベントリスト
title 文字列(UTF-8) タイトル
event_url 文字列(UTF-8) connpass.com 上のURL

https://connpass.com/api/v1/event/?keyword=python

完成図

スクリーンショット 2018-12-18 19.14.01.png

JSONの値を取得する

Codable

レスポンスの取得にはCodableを使用しています。
SwiftyJSONなどのライブラリを使用してJSON形式のデータを構造体に変換するなどの処理をする方法もありますが、CodableはSwiftが提供しておりライブラリを使わずシンプルに記述できるので使いました。

CodableでconnpassAPIのデータを変換します。

struct Resultsfield: Codable {
    var events: [Events]
    struct Events: Codable {
        var title: String
        var event_url: String
    }
}

APIを叩く

connpassAPIを叩くためにURLSessionを使いました。
URLSessionとはリクエストを受けて通信を行うクラスです。

struct Connpass {
    //非同期処理の後にクロージャを実行する
    static func fetchEvent(completion: @escaping (Resultsfield) -> Swift.Void) {        
        let url = "https://connpass.com/api/v1/event/?keyword=python" 
        //URLComponentsはクエリストリングの追加などが可能       
        let urlComponents = URLComponents(string: url)
        //非同期で通信を行う
        let task = URLSession.shared.dataTask(with: (urlComponents?.url!)!) { data, response, error in            

            guard let jsonData = data else {
                return
            }

            do {
                //jsonのマッピング
                let resultsfields = try JSONDecoder().decode(Resultsfield.self, from: jsonData)
                completion(resultsfields)

            } catch {
                print(error.localizedDescription)
            }
        }
        ////task.resume()メソッドを実行すると通信が開始される
        task.resume()
    }
}

tableViewにデータを表示させる

今回はextensionを使いクラスに定義を追加しました。
拡張先ではcellに取ってきた値を代入する処理をしています。

extension ViewController: UITableViewDataSource {

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = UITableViewCell(style: .subtitle, reuseIdentifier: "cell")
        let resultsfield = resultsfields.events[indexPath.row]
        cell.textLabel?.text = resultsfield.title
        cell.detailTextLabel?.text = resultsfield.event_url
        return cell
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return resultsfields.events.count
    }  
}

SafariServices

遷移先webページをSafariビューっぽい感じにするために
SFSafariViewControllerを使用します。
SafariServicesをimportして下記のように記述します。

extension ViewController: UITableViewDelegate {

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        let resultsfield = resultsfields.events[indexPath.row]
        let webPage = resultsfield.event_url
        let safariVC = SFSafariViewController(url: NSURL(string: webPage)! as URL)
        present(safariVC, animated: true, completion: nil)
    }
}

ソースコード

全体としては下記のようになります。

viewcontroller.swift
import UIKit
import SafariServices

struct Resultsfield: Codable {
    var events: [Events]
    struct Events: Codable {
        var title: String
        var event_url: String
    }
}

struct Connpass {

    static func fetchEvent(completion: @escaping (Resultsfield) -> Swift.Void) {        
        let url = "https://connpass.com/api/v1/event/?keyword=python"        
        let urlComponents = URLComponents(string: url)
        let task = URLSession.shared.dataTask(with: (urlComponents?.url!)!) { data, response, error in            

            guard let jsonData = data else {
                return
            }

            do {
                let resultsfields = try JSONDecoder().decode(Resultsfield.self, from: jsonData)
                completion(resultsfields)

            } catch {
                print(error.localizedDescription)
            }
        }
        task.resume()
    }
}


class ViewController: UIViewController {

    private var tableView = UITableView()
    var resultsfields: Resultsfield = Resultsfield(events: [])

    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.delegate = self
        tableView.frame = view.frame
        tableView.dataSource = self
        view.addSubview(tableView)

        Connpass.fetchEvent(completion: { (resultsfields) in
            self.resultsfields = resultsfields
            DispatchQueue.main.async {
                self.tableView.reloadData()
            }
        })

    }    
}

extension ViewController: UITableViewDataSource {

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = UITableViewCell(style: .subtitle, reuseIdentifier: "cell")
        let resultsfield = resultsfields.events[indexPath.row]
        cell.textLabel?.text = resultsfield.title
        cell.detailTextLabel?.text = resultsfield.event_url
        return cell
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return resultsfields.events.count
    }  
}
extension ViewController: UITableViewDelegate {

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        let resultsfield = resultsfields.events[indexPath.row]
        let webPage = resultsfield.event_url
        let safariVC = SFSafariViewController(url: NSURL(string: webPage)! as URL)
        present(safariVC, animated: true, completion: nil)
    }
}

最後に

最初は基礎文法などをわかっておらずコピペ頼りな所もあったのですが
このメソッドはどういう意味をもっているという理解や自分で一から作り上げる事が
やっぱり一番の近道だなと作っていて感じました。

追加機能として検索機能やソート機能
RxSwiftに書き換えなどしているので、出来次第また記事をあげたいと思います!

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした