2015.12.20

探検!SwiftyJSON (前編)

■□トライフォート2015年度新卒社員による新企画!
■□活躍しているメンバーの持ち回りで、多種多様な記事を掲載していきます。

こんにちは、iOS アプリエンジニアの繪面です。

Swift その3 Advent Calendar 2015  21 日目の記事としても投稿させていただいております。

Swift 愛好会で記事の一部を発表しました。

探検!SwiftyJSON from Yuka Ezura

突然ですが、Swift はお好きでしょうか。

Objective-C とは異なった設計思想を持っていて、とてもおもしろいですよね!

弊社も来年、Swift 案件があるとかないとかで、すごく楽しみです!

ということで、Swift への理解を深めるべく、OSS のライブラリ、SwiftyJSON のソースコードを読んでみました。

SwiftyJSON (licence)

概要

JSON は複数の型を含むので、NSJSONSerialization でパースすると AnyObject 型が返ってきます。そのため、要素へのアクセス毎にキャストしなければなりませんが、SwiftyJSON はその処理や要素のアクセスに伴う型毎の差異の吸収をしてくれます。

そのため、SwiftyJSON 内部は「渡された型を判定し、その型に対応した処理を行う」ためのコードが大半を占めます。

また、複数の種類の型を受け入れ、[] でのアクセスや map の使用など、自身を配列を扱うかのように操作できます。

これをどのように実装しているのか、なぜそのような動作を実装できるのか、それを紐解いていきます。

構成

  • SwiftyJSON とは
  • 動作から処理を追ってみる
    • 型の判定
    • subscript
    • SequenceType, CollectionType
    • BooleanType
    • LiteralConvertible (後編)
  • プロトコルについて考察 (後編)
    • SequenceType, CollectionType から考えるプロトコル設計
    • 基本構文やシンタックスシュガーに隠れたプロトコル

SwiftyJSON とは

JSON 内の値のアクセスを簡単にしてくれるライブラリです。

例えば、下記のような JSON から値を取り出す際に、キャストしてアンラップしてキャストして…ということが必要になりますが、SwiftyJSON なら、これをたった一行で完結させてくれます。

動作から処理を追ってみる

動作毎に説明していきます。

また、理解を深めるために、SwiftyJSON の提供する JSON 構造体の動作を自作の構造体で実現してみました。(側だけなので、受け取った型毎に処理を分ける部分は省略します。)

下記の処理が正常に動くまでを確認します。

try0

型の判定

computed property として定義してある object の setter 内で判定しています。(var object: AnyObjectで検索すると見つかります)

switch 文内でキャストしつつ unwrap しています。

(キャスト可能であればキャストし、unwrap した値を変数(または定数) にいれてその case 節内に入ります)

備考:

NSNumber の中には真偽値も含まれます。(実態が 0, 1 のため)

NSNumber から Bool を識別するためには objCTypeを使いますが、こちらの説明は省略します。

該当箇所(一部)

インデックス (subscript)

subscript メソッドを実装することで下記の操作を可能としています。

もう少し詳しい説明はこちら (subscript 説明)

該当箇所(一部)

try1

SequenceType, CollectionType

下記の処理を実現するために、JSON に SequenceType, CollectionType を実装しています。

SequenceType

SequenceType は「次の要素へのアクセスと遷移ができる」機能をクラスや構造体に付与します。

Array をイメージすると分かりやすいと思います。

mapfor in も 「array から一つ要素を受け取り処理し、そのあと、また次の要素を受け取る」という動作をしています。

それを実現するためのメソッドとして下記を実装します。

try2

CollectionType

CollectionType は SequenceType を継承しています。

SequenceType の「次の要素へのアクセスと遷移ができる」機能に「最初と最後が定義されていること、インデックスを指定して要素を取得可能であること」が追加されています。

try3

BooleanType

真偽値としての機能を付与するには、BooleanTypeプロトコルが必要です。

try4

前編まとめ

SwiftyJSON は受け取ったオブジェクト・値の型毎に対応した処理を内部的に実行し、型を隠蔽してくれます。

subscript, SequenceType, CollectionType, BooleanType などのプロトコルを実装しています。(その他にも printable プロトコルや演算子の拡張などが実装されていますが、今回は省略します)

try 最終結果

後編では、「LiteralConvertible」、「SequenceType, CollectionType から考えるプロトコル設計」、「基本構文やシンタックスシュガーに隠れたプロトコル」について説明します。

トライフォートで働きませんか?

トライフォートで働きませんか?
弊社ではエンジニア、デザイナー、ディレクター、プランナーを随時募集しています。
ゲームやサービスが好きで、新しいことにチャレンジしたい、世界に強いインパクトを残したい、という人を探しています!
我こそは、という人は是非ご応募ください!