読者です 読者をやめる 読者になる 読者になる

知行合一

とか言ってみる

【Swift】AloamofireとSwiftyJsonについて整理

swift

◼︎SwiftyJson整理
ただ、
http://qiita.com/yuta-t/items/1b6dfe34fa8537cf3329
の内容を書き写しただけのやつ

qiitaのapiの場合

[
{ title: "AlamofireとswiftyJsonで〜",
body: "はじめに〜",
created_at: "2015-12-03"
},
{ title: "Optionalを〜",
body: "この記事は〜",
created_at: "2015-12-04"
}
]

配列の中に辞書型
1つの辞書型が1つの記事

{ title: "AlamofireとswiftyJsonで〜",
	  body: "はじめに〜",
	  created_at: "2015-12-03"
}

{title: "タイトル"}
キーと値
この表現形式をJSON


◼︎Alamofireのrequestメソッド
引数はmethodURLString

methodはenumでどっかに定義、URLStringはURLをStringで書いてあるものでok

Alamofire.request(.GET, "https://qiita.com/api/v2/items")

requestメソッドに続けて、responseJSONメソッドを使用する。
responseJSONメソッドは1つの関数を引数に取るので、その関数をクロージャ

Alamofire.request(.GET, "https://qiita.com/api/v2/items")
    .responseJSON { response in
        // ここに処理を記述していく
    }

このresponseと定義したResponse型の引数は以下のような4つのプロパティをもつ

public let request: NSURLRequest?
public let response: NSHTTPURLResponse?
public let data: NSDAta?
public let result: Result<Value, Error>

記事の取得に使うのは4番目のresultだけ。
resultの型はResult。
Resultはenumで定義されており、
Success or Failureを値に取り、
Successの場合には値を持っている。

Alamofireはこのvalueを取得するためにvalueというプロパティを用意してある。

Alamofire.request(.GET, "https://qiita.com/api/v2/items")
    .responseJSON { response in
        print(response.result.value) // responseのresultプロパティのvalueプロパティをコンソールに出力
    }

ここまでで取得はできるので、ここからSwiftyJSONの出番。
SwiftyJSONはJSON型という、swiftyJSONが定義した型にデータを変換してからそのデータを扱う。

<ここでguardについて>=================================
◼︎swift2.0で追加されたguardの有効活用

//nilの場合にreturnしたい場合
func sample(num: Int?){
	if num == nil{
		return
	}
	//ここからメイン処理
	print(num!)
}

//guardを使うと
func sample(num: Int?){
	guard let n = num else{
		return
	}
	print(n)
}

===================================================
JSON型はAnyObject型からイニシャライズすることができるので、

public struct JSON {
	public init(_ object: AnyObject){
		self.object = object
	}
}

先ほどのresponse.result.valueをアンラップして引数に渡してあげる

Alamofire.request(.GET, "https://qiita.com/api/v2/items")
	.responseJSON { response in
		guard let object = response.result.value else{
			return
		}

		let json = JSON(object)

	}

これでJSON型に変換できました。

まずは記事の一覧を1つ1つの記事に分解していく。
これにはforEachメソッドを使用する.
(forEachメソッドswiftの標準ライブラリにあるSequenceTypeプロトコルに定義されている。
JSON型はSequenceTypeプロトコルに準拠しているので、このメソッドが使える。)

実際に使うと...

let json = JSON(object)
json.forEach{(String, JSON) in
	code
}

ここでStringにはその要素が何番目かという情報が入り、
JSONには記事1つのデータが入る。

今回は記事が何番目かという情報は使わないので、変数名をつけずに
アンダースコアにしておく。

let json = JSON(object)
json.forEach{(_, json) in
	//ここに処理を書いていく
}

例えば記事のタイトルを取得したい時は

let json = JSON(object)
json.forEach{(_, json) in
	json["title"]//jsonから"title"がキーのものを取得
}

(これはJSON型にsubsriptが実装されているから。
subscriptは配列や辞書型で扱うように、[]をメソッドとして使えるようにするもの)

しかし、subscriptの返り値はJSON型となっているので、
型の変換をしよう!
そのために、JSON構造体に定義されているstringプロパティを使う。

extension JSON{
	//Optional String
	public var string: String? {
		get {
			switch self.type{
			case .String:
				return self.object as? String
			default:
				return nil
			}
		}
	}

	...
}

stringプロパティはString型にキャストできればそれを、
できなければnilを返すメソッドで返り値はString?型となる。
printしてみると

let json = JSON(object)
json.forEach { (_, json) in
	print(json["title"].string)//記事タイトルを表示	
}

続いて、投稿者のユーザーIDを取得する。
qiitaAPIのドキュメントを見ると、投稿者のユーザーIDは
"user"というキー値の中の"id"というキーの値に格納されている。
つまり、二重の辞書型に入ってる。

が、これもSwiftyJSONで書ける。

let json = JSON(object)
json.forEach { (_, json) in
	json["title"].string
	print(json["user"]["id"].string) //投稿者のユーザーIDを表示
}

ということで、タイトルとidを保存!!

//インスタンス変数
var articles: [[String: String?]] = [] // 記事を入れるプロパティを定義

let json = JSON(object)
json.forEach{ (_, json) in
	let article: [String: String?] = [
		"title": json["title"].string,
		"userId": json["user"]["id"].string
	]
	self.articles.append(article)//配列に入れる
}

print(self.articles)

あとは、tableviewとかで

let article = articles[indexPath.row]
cell.textLabel?.text = article["title"]!

みたいな感じで。