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

Swift3からAPIを叩いてJSONの値を取得する

More than 3 years have passed since last update.

iPhoneアプリ作成の勉強中、ボタンをタップして文字列を表示するという例題があったので
APIを叩いてJSONで値をもらって表示できるかな?と思いトライした記録です。
超初心者の写経中の遊び心という脱線の記録とも言います。

勉強の元ネタ

  • 絶対に挫折しないiPhoneアプリ開発「超」入門 増補改訂第5版 Swift3&iOS 10.1移行完全対応
    • P.148 UI部品の配置にあるHelloというアプリ

元ネタから改造した点

  • Before

    • ボタンをタップするとLabelに予め設定したテキストが表示されるのみ
  • After1

    • ボタンを2つ配置し、タップするボタンに応じ予め設定したテキストが表示されるように改造

    アクションの内容としては
    * 1つ目は、任意の文字列を表示させる
    * 2つ目は、起動時に表示される文字列を表示させる
    といった感じ。

  • After2 ← 今ココ

    • 1つ目をタップすると"inet-ip.info/json"にhttp接続しグローバルIPとISPのFQDNを取得、表示する。
    • 2つ目をタップすると、起動時に表示される文字列を表示する。

注意点

  1. XCodeのデフォルト設定ではhttps通信しか許可されないようで、以下の対処が必要でした。

    • Project内のinfo.plistにApp Transport Security Settingsを追加
    • App Transport Security Settings配下に、Allow Arbitrary Loadsを追加し値を”YES”に変更
  2. 後述の参考URLの記事をベースに実装していましたが、取得した値を表示する処理をメインスレッドで行わない場合、どうも処理落ちしているっぽいことが判明しました。

    DispatchQueue.main.asyncというのを使って、メインスレッドで表示させることで解消。レスポンスもUPし(゚д゚)ウマーな感じ。がしましたが気のせいだったかも。。。

  3. inet-ip.infoは、GETメソッドでアクセスする必要がありました。(後述のコード参照)

汚いソースのお披露目

書籍と参考URLをベースに実装した結果がコチラ

ViewController.swift
import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var label: UILabel!
    @IBAction func getNwinfo() {
        // 取得したJSONを格納する変数を定義
        var getJson: NSDictionary!

        // 抽出した"ip"を格納する変数を定義
        var jsonIp = ""

        // 抽出した"hostname"を格納する変数を定義
        var jsonHostname = ""

        // 抽出した"ip"と"hostname"を結合する変数を定義
        var jsonString = ""

        // API接続先
        let urlStr = "http://inet-ip.info/json"

        if let url = URL(string: urlStr) {
            let req = NSMutableURLRequest(url: url)
            req.httpMethod = "GET"
            // req.httpBody = "userId=\(self.userId)&code=\(self.code)".data(using: String.Encoding.utf8)
            let task = URLSession.shared.dataTask(with: req as URLRequest, completionHandler: { (data, resp, err) in
                print(resp!.url!)
                print(NSString(data: data!, encoding: String.Encoding.utf8.rawValue) as Any)

                // 受け取ったdataをJSONパース、エラーならcatchへジャンプ
                do {
                    // dataをJSONパースし、変数"getJson"に格納
                    getJson = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableContainers) as! NSDictionary

                    jsonIp = (getJson["IP"] as? String)!
                    jsonHostname = (getJson["Hostname"] as? String)!
                    jsonString = "m9(・∀・)NW情報ゲトしますた!\n\nGlobalIP : " + jsonIp + "\nISP FQDN : " + jsonHostname

                    print (jsonIp)
                    print (jsonHostname)

                    DispatchQueue.main.async{
                        self.label.text = jsonString
                    }
                } catch {
                    print ("json error")
                    return
                }
            })
            task.resume()
        }
    }
    @IBAction func goBack() {
        label.text = "(๑•̀ㅁ•́๑)✧シャキーン"
    }
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}

参考URL

Special Thanks

@Ryuichirou

nya193
意識遠い系のエンジニアです。お昼寝大好きです。 時限投稿したいときは、はてなブログに書くことがあります。
http://init6.hatenablog.com/
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