ベーシック認証とJSONとUIwebView。
ベーシック認証が設定されているサーバーのJSONを読み込んでやりたかった事。
① 画像までのパスを取得してUIImageに設定したかった。
② UIWebViewに読み込みたいページのURLを取得して表示したかった。
で、、、
JSONに関してはAlamofireを使ってJSONを取得
{
"responseData": {
"feed": {
"entries": [
{
"id": "220",
"title": "タイトルが入ります。",
"text": "記事の本文です。",
"cat": "カテゴリー",
"subCat": "サブカテゴリー",
"thumbnail": "http://◯◯◯.com/img/entry/☓☓☓.jpg",
"url": "http://◯◯◯.com/△△△△.html"
}
]
}
}
}
というJSONデータを読み込みます。
let user = "userId"
let password = "userPass"
// JSONのパース
func parse(url: String, completion: (([JSON]?, NSError?) -> Void)){
var url = NSURL(string: url)
Alamofire.request(.GET, url!, parameters: nil, encoding: .JSON)
.authenticate(user: user, password: password)
.responseJSON{ (request, response, data, error) in
let json = JSON(data!)
let entries = json["responseData"]["feed"]["entries"].array
completion(entries, error)
}
}
.authenticate(user: user, password: password)
と、この一文を足すとベーシック認証下のJSONは読み込めましたが、画像、UIWebViewへの埋め込みはできませんでした。
色々と考えたのですが結局JSONファイルを修正しました。
{
"responseData": {
"feed": {
"entries": [
{
"id": "220",
"title": "タイトルが入ります。",
"text": "記事の本文です。",
"cat": "カテゴリー",
"subCat": "サブカテゴリー",
"thumbnail": "http://userId:userPass@◯◯◯.com/img/entry/☓☓☓.jpg",
"url": "http://userId:userPass@◯◯◯.com/△△△△.html"
}
]
}
}
}
てな感じで、URLに直接ユーザー名・パスワードを埋め込みました。
(このページを参照)
http://qiita.com/ngkazu/items/6da021edf177f40e1f26
これで無事、表示しました。
開発中のアプリ内のJSONキャッシュは結構きついのでキャッシュ対策をしておく方が無難です。
http://◯◯◯.com/▲▲▲▲▲.json?123
とURLに?〜をつければOK。
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)が選択された")
}
}
上から順番に処理してくれると思い込んでいたので、「あれ?」っとなったのですが、考えてみれば当たり前のことでした。