プログラミングBlog

SwiftUITutorial Building Lists and Navigation①

SwiftUITutorialで学んだことをまとめていきます。

Create a Landmark Model

Section1で学べること

  • Jsonファイル読み込み
  • 読み込んだJsonファイルをStructに詰め込む

struct

構造体のことで以下の特徴がある

  • 継承できない
  • クラスは参照型で構造体は値型

Hashable

hashについてはこちら
tokuty.hatenablog.com

Codable

API通信等で取得したJsonやプロパティリストを任意のデータ型に変換するプロトコル
これがないとJsonからStructのデータ変換が上手くいかない。

CLLocationCoordinate2D

位置情報を扱うときの型
coodinate.latitude:緯度 double型
coodinate.longitude:経度 double型

ファイルまでのパスを取得

    guard let file = Bundle.main.url(forResource: filename, withExtension: nil)
    else {
        fatalError("Couldn't find \(filename) in main bundle.")
    }

ファイル内容を取得

    do {
        data = try Data(contentsOf: file)
    } catch {
        fatalError("Couldn't load \(filename) from main bundle:\n\(error)")
    }

Jsonデータをデコード

    do {
        let decoder = JSONDecoder()
        return try decoder.decode(T.self, from: data)
    } catch {
        fatalError("Couldn't parse \(filename) as \(T.self):\n\(error)")
    }

作成したファイル

Landmark.swift

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
    }
}

ModelData.swift

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) in 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)")
    }
}