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

[Swift 1.1] swiftで api を叩いて、JSONをパースして、表示させる方法 (xcodeは6.1, iOSは8.1)

More than 5 years have passed since last update.

対応バージョン

swift 1.1
xcode 6.1
iOS 8.1

目標

「yahooニュースのRSSをJSONで配ってるapiを叩いて、JSONデータをゲトして、テーブルでひ項目表示させて、セルをタップしたらwebViewで元記事が見れる」ところまで実装。

Playgroundでやってみました。

import UIKit
import XCPlayground

//make URL of google feed api
var urlString = "http://ajax.googleapis.com/ajax/services/feed/load?v=1.0&q=http://rss.itmedia.co.jp/rss/2.0/news_bursts.xml&num=8"
var url = NSURL(string: urlString)

//download by NSSession
var task = NSURLSession.sharedSession().dataTaskWithURL(url!, completionHandler:{data, response, error in
    //convert json data to dictionary
    var dict = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as NSDictionary

    println(dict)
})

task.resume()

XCPSetExecutionShouldContinueIndefinitely(continueIndefinitely: true)

Screen Shot 2014-11-13 at 15.43.38.png

とりあえずこんな感じでゲトできる。

titleだけ表示させてみる

import UIKit
import XCPlayground

//make URL of google feed api
var urlString = "http://ajax.googleapis.com/ajax/services/feed/load?v=1.0&q=http://rss.itmedia.co.jp/rss/2.0/news_bursts.xml&num=8"
var url = NSURL(string: urlString)

//download by NSSession
var task = NSURLSession.sharedSession().dataTaskWithURL(url!, completionHandler:{data, response, error in
    //convert json data to dictionary
    var dict = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as NSDictionary

    //get responseData, feed, entries
    var responseData = dict["responseData"] as NSDictionary
    var feed = responseData["feed"] as NSDictionary
    var entries = feed["entries"] as NSArray

    //extract entries
    for entry in entries {
        println(entry["title"])
    }

    println(dict)
})

task.resume()

XCPSetExecutionShouldContinueIndefinitely(continueIndefinitely: true)

Screen Shot 2014-11-13 at 15.38.41.png

できた!!

テーブルで表示させてみる

playgroundを離れ、普通のアプリ制作のフローでいきます。

細かいところは一旦置いといて。

import UIKit

class ViewController: UITableViewController {

    //array of entries
    var entries = NSArray()
    let newsUrlString = "http://ajax.googleapis.com/ajax/services/feed/load?v=1.0&q=http://rss.itmedia.co.jp/rss/2.0/news_bursts.xml&num=8"

    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.
    }

    //count cell of table view
    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return entries.count
    }

    //make tableView
    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        //get cell
        var cell = tableView.dequeueReusableCellWithIdentifier("news") as UITableViewCell

        //get entry
        var entry = entries[indexPath.row] as NSDictionary

        //set title
        cell.textLabel.text = entry["title"] as? String

        return cell
    }

    //make reload button
    @IBAction func refresh(sender: AnyObject) {
        let url = NSURL(string: newsUrlString)!

        var task = NSURLSession.sharedSession().dataTaskWithURL(url, completionHandler: {data, response, error in
            // conver json to dictionary
            var dict = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as NSDictionary

            // get responseData entries
            if var responseData = dict["responseData"] as? NSDictionary {
                if var feed = responseData["feed"] as? NSDictionary {
                    if var entries = feed["entries"] as? NSArray {
                        // set array of entries
                        self.entries = entries
                    }
                }
            }
            //switch to main thread to relad table view
            dispatch_async(dispatch_get_main_queue(), {
                //reload table view
                self.tableView.reloadData()
            })
        })
        task.resume()
    }
}

はじめにビルドすると、、、

Screen Shot 2014-11-13 at 16.07.34.png

リロードボタンを押すと

Screen Shot 2014-11-13 at 16.07.39.png

読み込まれた!

リロードボタンの実装はstoryboardからやりました。
navigationbarにbarbuttonitemを載せ、identifierをrefreshにして、assistantEditorを開いてViewControllerにCtrl+ドラッグアンドドロップしただけです。

本文も表示

詳細のViewControllerを増やす

Screen Shot 2014-11-13 at 16.13.28.png
storyboardからViewCotnrollerを選択して、ドラッグアンドドロップ。

Screen Shot 2014-11-13 at 16.15.40.png
TableViewのViewControllerと今回のViewControllerを紐付け。Segueる。
Storyboardの左っかわで、Ctrl+ドラッグアンドドロップで紐付けできます。

Screen Shot 2014-11-13 at 16.16.18.png
Segueのidentifierを決める

以下のコードを追加して、segueを追加します。

    //add segue
    override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        // Segue
        performSegueWithIdentifier("detail", sender: entries[indexPath.row])
    }

Screen Shot 2014-11-13 at 16.19.17.png
ビルドしてみるとこんな感じ。
テーブルのセルをタップすると新しいViewControllerが呼ばれて遷移する。

WebView

  • DetailControllerにWebViewを追加

storyboardでドラッグアンドドロップしたらOK。

  • DetailControllerにアウトレットを追加

assistantEditorを表示して、Ctrl+ドラッグアンドドロップ。

Screen Shot 2014-11-13 at 16.33.49.png

  • URLを読み込むコードをかく
import Foundation
import UIKit

class DetailController: UIViewController {

    @IBOutlet weak var webView: UIWebView!

    var entry = NSDictionary()

    override func viewDidLoad() {
        super.viewDidLoad()

        //read URL by webView
        var url = NSURL(string: self.entry["link"] as String)
        var request = NSURLRequest(URL: url!)
        webView.loadRequest(request)
    }
}
  • ViewController側で表示するエントリーをDetailControllerに渡すところを何とかする
    // send entry to DetailController
    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        if segue.identifier == "detail" {
            // get DetailController
            var detailController = segue.destinationViewController as DetailController

            // set entry
            detailController.entry = sender as NSDictionary
        }
    }

さっきsegueを追加したコードの下あたり、@IBAction func refresh の上辺りに追記。

  • ビルド

いい感じー

Screen Shot 2014-11-13 at 16.40.16.png

とりあえず

とりあえず大枠ができたので、これから自分なりにカスタマイズしていくのですが、それはまた次回、、、

(swift1.1と1.0ってかなり違うんですね。。。2.0でいいのでは・・・)

参考

colorrabbit
creator.
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