はじめに
前回からの続きでSwiftUIのチュートリアル入門になります。
もと記事サイト

Step0
前回までに作成したプロジェクトと、今回のチュートリアルでダウンロードできるjsonファイルを使って、jsonファイルのデータをリスト表示していきます。
Step1
チュートリアルに添付されているプロジェクトをダウンロードし、その中にあるlandmarkData.json
を現在作業しているXcodeプロジェクトのナビゲーションにドラッグ&ドロップします。
すると、ダイアログが表示されるので画像のようにチェックをします。(Add to targetsはご自身のプロジェクトの名前になっています。)

こんな感じでlandmarkData.json
が追加されています。

Step2
上の方にあるナビゲーションバーからFile > New > Fileを選択。

ファイル一覧が表示されるので、User Interface
欄にある、SwiftUI View
を選択して、Next
ボタンを押します。ファイル名をLandmark.swift
とし、新規で作成します。

Step3
Landmark
という名前のStructを作成します。landmarkData.json
から取り出したランドマークごとのデータを保存するために使用します。Codable
を付けることで、json内の項目とStruct内の項目をマッピングしてデータを自動で取得できるようにしています。
import Foundation
struct Landmark: Hashable, Codable {
var id: Int
var name: String
var park: String
var state: String
var description: String
}
Step4
プロジェクトナビゲーションにあるAssets.xcassets
をクリックし、
チュートリアルのプロジェクト内にあるJPGファイルをドラッグ&ドロップします。

Step5
jsonファイルからファイル名を読み込むためのimageName
プロパティと、Viewに画像を表示するためにasset catalogから画像を取得するimage
プロパティを追加します。
import Foundation
import SwiftUI
struct Landmark: Hashable, Codable {
var id: Int
var name: String
var park: String
var state: String
var description: String
private var imageName: String
var image: Image {
Image(imageName)
}
}
Step6
jsonファイルから経度、緯度を取得するためのcoordinates
プロパティを追加します。landmarkData.json
を確認すると、coordinates
の中にlongitude
とlatitude
が入れ子になっています。
StructとしてCoordinates
を新規作成し、Landmark
にprivate var coordinates: Coordinates
を持たせています。
import Foundation
import SwiftUI
struct Landmark: Hashable, Codable {
var id: Int
var name: String
var park: String
var state: String
var description: String
private var imageName: String
var image: Image {
Image(imageName)
}
private var coordinates: Coordinates
struct Coordinates: Hashable, Codable {
var latitude: Double
var longitude: Double
}
}
Step7
経度、緯度からMapKit frameworkのCLLocationCoordinate2D
を生成します。
import Foundation
import SwiftUI
import CoreLocation
struct Landmark: Hashable, Codable {
var id: Int
var name: String
var park: String
var state: String
var description: String
private var imageName: String
var image: Image {
Image(imageName)
}
private var coordinates: Coordinates
var locationCoordinate: CLLocationCoordinate2D {
CLLocationCoordinate2D(
latitude: coordinates.latitude,
longitude: coordinates.longitude)
}
struct Coordinates: Hashable, Codable {
var latitude: Double
var longitude: Double
}
}
Step8
Step2と同じ手順でModelData.swift
ファイルを作成します。
Step9
load(_:)
メソッドを作成し、パラメータで渡したjsonファイル名を使ってjsonを取得し、jsonをオブジェクトに変換します。
import Foundation
func load<T: Decodable>(_ filename: String) -> T {
let data: Data
guard let file = Bundle.main.url(forResource: filename, withExtension: nil)
else {
fatalError("Couldn't find \(filename) from main bundle.")
}
do {
data = try Data(contentsOf: file)
} catch {
fatalError("Couldn't load \(filename) from main bundle:\n\(error)")
}
do {
let decoder = JSONDecoder()
return try decoder.decode(T.self, from: data)
} catch {
fatalError("Couldn't parse \(filename) as \(T.self):\n\(error)")
}
}
Step10
load(_:)
の呼び出しもとを作成します。
パラメータでlandmarkData.json
を渡し、ファイル名からjsonファイルを取得。
取得したjsonファイルからjsonを取得し、オブジェクトに変換したものを配列で返却しています。
import Foundation
var landmarks: [Landmark] = load("landmarkData.json")
func load<T: Decodable>(_ filename: String) -> T {
let data: Data
guard let file = Bundle.main.url(forResource: filename, withExtension: nil)
else {
fatalError("Couldn't find \(filename) from main bundle.")
}
do {
data = try Data(contentsOf: file)
} catch {
fatalError("Couldn't load \(filename) from main bundle:\n\(error)")
}
do {
let decoder = JSONDecoder()
return try decoder.decode(T.self, from: data)
} catch {
fatalError("Couldn't parse \(filename) as \(T.self):\n\(error)")
}
}
Step11
ファイルの役割ごとにグループ化し、管理しやすくします。
グループ化したいファイルをCommand
を押しながらクリックで選択、上部のナビゲーションバーからFile > New > Group from Selectionを選択します。

以下のようにファイルをグループ化して、フォルダに名前を付けました。

まとめ
リスト表示するための下準備で、あまりSwiftUI関係ない内容ではありましたが、
jsonからオブジェクトに変換するModelData.swift
に関しては勉強になったかなという感じでした。
次回からは実際にView側を作成していきます。
コメント