前節ではSwift内のデータの編集を紹介しました. この節では, これまでSwiftに直接書き込んでいたリストのデータをファイルから読み込んでみます。多くのアプリケーションは用いるデータを外部から得てくることがほとんどです. 今回はその1例としてJSONファイルを読み込んでリスト表示にしてみます.
-
SFSwiftUI03-2.swiftpm を開く (サンプルコード)
- 03-1を完了したコードと同様
- photos配列を空っぽにしている
- 後で読み込むためのJSONファイルが入っている
- データがないため, プレビューも何もない状態から始まることを確認
- 03-1を完了したコードと同様
コード1
|
|
初期状態
photos配列に何も入っていないのでリストには何も表示されません. photosにデータが必要になりますが,今回はSwiftファイルに直接データを書かず, PhotoData型に必要なデータを満たしているJSONファイルを読み込んでphotosに入れるようにしてみます.
ファイルのバンドル
今回読み込むJSONファイルはサンプルコードにすでに用意されており,App内に含んでいます. このようにファイルをApp内にあらかじめ含ませておくことを バンドル といいます. 今回はResourcesフォルダとその中身のphotos.jsonがバンドルされています.
JSONとは
JSON(JavaScript Object Notation)はWebでデータを取り扱うのにメジャーなファイル形式です. 「キー:値」 のペアと, その配列でデータを作るテキストファイルを指します.
-
[ ~ ] は配列, { ~ } はペア値のグループ を指します. カンマで区切りながら,下記のように記述します.
コード2
|
|
Resources/photos.jsonは, []配列の中に{}でまとめた2つのデータを持ってます. また{}の中のキーペアの値をみると,PhotoData構造体と同じ情報を持っていることがわかります.これからこのファイルを読み込んで, photos配列へ変換していきます.
まず, PhotoData構造体をJSONと相互に変換できるように準備します.
- PhotoData.swiftを開き, PhotoDataに Codable を追加する
- Codable: JSONからの変換とJSONへの変換ができるデータであるという宣言
- id = UUID()を id:String = UUID().uuidString へ変更
- UUID型はJSONで読めないため, .uuidStringで文字列に変える
コード3
|
|
次に, JSONファイルを読み込むための処理を書きます.
- 新規のファイルを作成, Resource.swiftに名前を変更し以下を記述する
- Resource.load( name: ext: ) を作成, 指定した名前のリソースを読めるようにする
- Bundle.main.url( forResource:withExtension ) でAppにバンドルしたファイルのURLを作成
- Data( contentsOf: ) でURLを指定すると, 読み込んだ内容がdata変数に代入される
- Data( contentOf: )は失敗がありうる(URLのミスなど). 失敗時に 例外 を返す
- 例外がある処理には try をつける. 本来は例外発生時の処理を書くが今回は割愛する
- 今回はtry!と記述し, 例外判定を無視する (※ただし例外が起きた時Appは止まる)
- 読み込んだ結果(data変数の中身)をreturnで返却する
コード4
|
|
次は再びPhotoData構造体に注目します. Resource.loadで読み込んだDataをPhotoDataに変換するコードを追加します.
- PhotoData.swiftを開き, static func parse( json: ) を追加する
- JSONから読み込んだDataを受け取る
- JSONDecoder().decode( … ) で, Data型をJSONとして読むことを試みる
- 失敗時に例外が発生するので, 今はtry!で例外を無視する
- [PhotoData].self は変換した後の型を指定している
- 変換後にPhotoData配列にするようdecoderに伝える
コード5
|
|
これで PhotoData.parse( json: ) を使うことでJSONファイルの中身を[PhotoData]に読み込めるようになりました. 次はこれを画面で使ってみます.
- ContentView.swiftを開き, photosを空配列から以下の記述に変更する
- Resource.load( name:ext: )で Resource/photos.json を読み込んでData型にする
- DataをPhotoData.parse()で, [PhotoData]へ変換する
|
|
結果
読み込みに成功するとプレビューに2つのデータが表示されます. 表示されたデータはResource/photos.jsonの内容となっていることを確認してください.