16272


現在、Google Sheets API を使って、Google スプレッドシートの情報を JSON で取得し、その結果をパースして TableView
に一覧表示するようなものを作ろうとしています。

現在書いている Swift 2 のコードはこちらです。

[code]

    let makeStatusUrl = "https://spreadsheets.google.com/feeds/list/1BCAOfRDmoFLyV-bcvjFQZ2St-qg7wAUQa7o_9cn-oL8/od6/public/basic?alt=json"
    let statusUrl = NSURL(string: makeStatusUrl)
    let task = NSURLSession.sharedSession().dataTaskWithURL(statusUrl!, completionHandler: { data, response, error in
    do {
        let dict = try NSJSONSerialization.JSONObjectWithData(data!, options: .MutableContainers) as! NSDictionary
        var feed = dict["feed"] as! NSDictionary
        var entry = feed["entry"] as! NSArray
    
        for content in entry {
            let content = content["content"] as! NSDictionary
            print(content)
        }
    } catch {
    }})
    task.resume()
    
[/code]

上記のコードだと、

[code]

    print(content)
    
[/code]

の部分で次の結果が吐き出されます。

[code]

    {
    "$t" = "name: iOS, index: 12";
    type = text;
    }
    {
    "$t" = "name: Android, index: -11";
    type = text;
    }
    {
    "$t" = "name: LINE, index: 20";
    type = text;
    }
    
[/code]

ここからが本題なのですが、上記出力結果の name と index の値をセットで取り出し、TableView に一覧表示させたいと思っています。

具体的には次のような感じです。画像では1行セットしていますが、この「iOS 12」の下に同じ形式で「Android -11」、「LINE
20」と続いていく感じです。  
[![](https://i.stack.imgur.com/oWcfa.png)](https://i.stack.imgur.com/oWcfa.png)

自分としては name と index を NSDictionary でセットし、それを表示するようにコードを書けばよいのでは
と思っていますが、初心者のためどのように書いたらよいか分かりません。

ご教授願います。

また、スタック・オーバーフロー も初心者ですので、不備などがありましたら回答、および編集などをしていただけると幸いです。


CC BY-SA 3.0
2015-09-04T17:22:08.757
16269
2015-10-16T16:09:29.337
2015-10-16T16:09:29.337
5519
10947
question
ios swift
Swift 2、NSDictionary から値を取り出す


前提

  1. テーブルビューのアウトレット接続とデリゲート設定が済んでいるものとする
  2. JSONダウンロードの実行ボタンとして「Reload」（`reload`関数が実行される）ボタンがあるものとする

* * *

データソース

テーブルビューに表示するデータは順序が必要なため、一般的には配列を使用する  
今回は`feed["entry"]`で取得できる配列をデータソースとして`var dataSource: [NSDictionary]`プロパティへ格納する

* * *

JSONのダウンロード

ダウンロードはバックグラウンドで行う  
ダウンロードの完了通知を受け取るためビューコントローラは`NSURLSessionDownloadDelegate`プロトコルを採用し`URLSession(session:
NSURLSession, downloadTask: NSURLSessionDownloadTask,
didFinishDownloadingToURL location: NSURL)`関数を実装する

* * *

JSONの解析

  1. テーブルのデータソースとして都合のよい配列を取得する
  2. 配列を`dataSource`プロパティへ格納する
  3. メインスレッドでテーブルを更新する（UIの更新はメインスレッドで行う）

* * *

テーブルのための整形

テーブルを更新したことで`tableView(tableView: UITableView, cellForRowAtIndexPath
indexPath: NSIndexPath) -> UITableViewCell`関数がデータソースの内容を元に実行される

ここでは配列から取り出したデータを表示に適したものへ整形しセルのラベルへセットする  
例）`name: iOS, index: 12` -> `iOS`と`12`へ

* * *

`ViewController.swift`:

[code]

    import UIKit
    
    class ViewController: UIViewController, NSURLSessionDownloadDelegate, UITableViewDelegate, UITableViewDataSource {
    
      @IBOutlet weak var tableView: UITableView!
      var dataSource: [NSDictionary]! = []
    
      override func viewDidLoad() {
        super.viewDidLoad()
      }
    
      @IBAction func reload(sender: AnyObject) {
        let url = "https://spreadsheets.google.com/feeds/list/1BCAOfRDmoFLyV-bcvjFQZ2St-qg7wAUQa7o_9cn-oL8/od6/public/basic?alt=json"
        let configuration = NSURLSessionConfiguration.backgroundSessionConfigurationWithIdentifier("Configuration")
        let session = NSURLSession(configuration: configuration, delegate: self, delegateQueue: nil)
        let task = session.downloadTaskWithURL(NSURL(string: url)!)
    
        task.resume()
      }
    
      func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didFinishDownloadingToURL location: NSURL) {
        let json = NSData(contentsOfURL: location)
        do {
          let dict = try NSJSONSerialization.JSONObjectWithData(json!, options: NSJSONReadingOptions.MutableContainers)
          let feed = dict["feed"] as! NSDictionary
          self.dataSource = feed["entry"] as! [NSDictionary]
    
          NSOperationQueue.mainQueue().addOperationWithBlock({ () -> Void in
            self.tableView?.reloadData()
          })
        } catch {
          print("JSON parse error")
        }
        session.finishTasksAndInvalidate()
      }
    
      func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
        return 44;
      }
    
      func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return dataSource.count;
      }
    
      func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Value1, reuseIdentifier: "cellId")
    
        let content = self.dataSource[indexPath.row]["content"] as! NSDictionary
        let raw = content["$t"] as? String
        let values = raw?.componentsSeparatedByString(", ") as [String]!
        let name = values[0].substringFromIndex(values[0].rangeOfString(": ")!.endIndex)
        let index = values[1].substringFromIndex(values[1].rangeOfString(": ")!.endIndex)
    
        cell.textLabel?.text = name
        cell.detailTextLabel?.text = index
    
        return cell
      }
    }
    
[/code]

* * *

実行画面:

[![画像の説明をここに入力](https://i.stack.imgur.com/5i8Bk.png)](https://i.stack.imgur.com/5i8Bk.png)


CC BY-SA 3.0
2015-09-04T20:52:43.780
16272
2015-09-05T15:10:29.150
2015-09-05T15:10:29.150
16269
answer