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)
これを書いている位置が悪かったわけで、
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)が選択された")
}
}
上から順番に処理してくれると思い込んでいたので、「あれ?」っとなったのですが、考えてみれば当たり前のことでした。