何でも一回はやってみよう。

気が向いた事は何でも一回試してるビール大好きなおっさんッス。

SwiftyJSONとAlamofireとTableView。

単純なんですけど、JSONを読み込んでその項目分のセクション、行数を作成するときにハマりました。

import UIKit
import SwiftyJSON
import Alamofire
class SearchViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
    var jsonURLString = "http://◯◯◯◯◯◯.json"
    // セクションのタイトル
    var sectionArray: NSMutableArray = []
    // 各要素
    var itemArray: NSMutableArray = []
    var sectionKosu: Int = Int()
    override func viewDidLoad() {
        super.viewDidLoad()
        // JSONのパース
        Alamofire.request(.GET, jsonURLString, parameters: nil, encoding: .JSON)
            .responseJSON { (request, response, responseData, error) -> Void in
                if let data: AnyObject = responseData {
                    let results = JSON(data)
                    let count: Int = results["responseData"]["feed"]["entries"].count

                    for index in 0..<count {
                        // タイトルの抜き出し
                        let title = results["responseData"]["feed"]["entries"][index]["ttl"].string!
                        self.sectionArray.addObject(title)

                        // セルの項目
                        let items: AnyObject = results["responseData"]["feed"]["entries"][index]["item"].rawValue
                        self.itemArray.addObject(items)
                    }
                    let barHeight: CGFloat = UIApplication.sharedApplication().statusBarFrame.size.height
                    let displayWidth: CGFloat = self.view.frame.width
                    let displayHeight: CGFloat = self.view.frame.height
                }
        }
        let myTableView: UITableView = UITableView(frame: CGRect(x: 0, y: 140 + barHeight, width: displayWidth, height: displayHeight - (140 + barHeight)))
        myTableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "MyCell")
        myTableView.dataSource = self
        myTableView.delegate = self
        self.view.addSubview(myTableView)
   }
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
    // セクションごとの行数を返す
    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return self.itemArray[section].count
    }
    // 各行に表示するセルを返す
    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("MyCell", forIndexPath: indexPath) as! UITableViewCell
        // セルに表示するテキストを設定
        cell.textLabel?.text = "セル" + (indexPath.row).description
        cell.detailTextLabel?.text = "サブタイトル"
        return cell
    }
    // セクション数
    func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return self.sectionArray.count
    }
    // セクションタイトル
    func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        return sectionArray[section] as? String
    }
    func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        println("セクション\(indexPath.section)のセル\(indexPath.row)が選択された")
    }
}

ざっとコードはこんな感じ。

// セクション数
    func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return self.sectionArray.count
    }

JSONをパースしてからセクション数を決定するのですが、上記のコードでは必ずセクション数は0になります。
セクションのタイトルも無ければ行数も0。
何でかなー?とハマること数時間。。

何故かというと
パースしてる最中にテーブルを作成してしまっている
から。

self.view.addSubview(myTableView)

これを書いている位置が悪かったわけで、

Alamofire.request(.GET, jsonURLString, parameters: nil, encoding: .JSON)
            .responseJSON { (request, response, responseData, error) -> Void in

                (中略)
                    self.view.addSubview(myTableView)
                }

        }

JSONデータを受け取って処理してからaddSubViewしないとダメ。
.responseJSON {} の中ですね。

import UIKit
import SwiftyJSON
import Alamofire
class SearchViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
    var jsonURLString = "◯◯◯◯◯◯.json"
    // セクションのタイトル
    var sectionArray: NSMutableArray = []
    // 各要素
    var itemArray: NSMutableArray = []
    var sectionKosu: Int = Int()
    override func viewDidLoad() {
        super.viewDidLoad()
        // JSONのパース
        Alamofire.request(.GET, jsonURLString, parameters: nil, encoding: .JSON)
            .responseJSON { (request, response, responseData, error) -> Void in
                if let data: AnyObject = responseData {
                    let results = JSON(data)
                    let count: Int = results["responseData"]["feed"]["entries"].count
                    for index in 0..<count {
                        // タイトルの抜き出し
                        let title = results["responseData"]["feed"]["entries"][index]["ttl"].string!
                        self.sectionArray.addObject(title)
                        // セルの項目
                        let items: AnyObject = results["responseData"]["feed"]["entries"][index]["item"].rawValue
                        self.itemArray.addObject(items)
                    }
                 self.sectionKosu = self.sectionArray.count
                    let barHeight: CGFloat = UIApplication.sharedApplication().statusBarFrame.size.height
                    let displayWidth: CGFloat = self.view.frame.width
                    let displayHeight: CGFloat = self.view.frame.height
                    let myTableView: UITableView = UITableView(frame: CGRect(x: 0, y: 140 + barHeight, width: displayWidth, height: displayHeight - (140 + barHeight)))
                    myTableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "MyCell")
                    myTableView.dataSource = self
                    myTableView.delegate = self
                    self.view.addSubview(myTableView)
                }
        }
   }
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
    // セクションごとの行数を返す
    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return self.itemArray[section].count
    }
    // 各行に表示するセルを返す
    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("MyCell", forIndexPath: indexPath) as! UITableViewCell
        // セルに表示するテキストを設定
        cell.textLabel?.text = "セル" + (indexPath.row).description
        cell.detailTextLabel?.text = "サブタイトル"
        return cell
    }
    // セクション数
    func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return self.sectionArray.count
    }
    // セクションタイトル
    func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        return sectionArray[section] as? String
    }
    func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        println("セクション\(indexPath.section)のセル\(indexPath.row)が選択された")
    }
}

上から順番に処理してくれると思い込んでいたので、「あれ?」っとなったのですが、考えてみれば当たり前のことでした。