SwiftUI Tutorilasを読み解く パート2

# この記事は何？
[前回](https://qiita.com/chino_tweet/items/9565dc4b5e7378fea2ef)の続きです。
今回は、Landmark.swiftファイルを読み解きたいと思います。

# Landmark.swift
主に、観光地を表現する構造体を記述しているファイルです。
プロジェクトのModelグループにあります。

## ソースコード
最初にコード全体を見ておきます。
SwiftUIのチュートリアルではありますが、やはりSwiftUIの概念は無きに等しいと言えます。
全体としては、次の4つに分けて読むことができます。

- フレームワークのインポート
- `Landmark` 型の定義
- `Landmark` 型の拡張
- `Coordinates` 型の定義

````Swift:Landmark.swift
import SwiftUI
import CoreLocation

struct Landmark: Hashable, Codable {
    var id: Int
    var name: String
    fileprivate var imageName: String
    fileprivate var coordinates: Coordinates
    var state: String
    var park: String
    var category: Category

    var locationCoordinate: CLLocationCoordinate2D {
        CLLocationCoordinate2D(
            latitude: coordinates.latitude,
            longitude: coordinates.longitude)
    }

    enum Category: String, CaseIterable, Codable, Hashable {
        case featured = "Featured"
        case lakes = "Lakes"
        case rivers = "Rivers"
    }
}

extension Landmark {
    var image: Image {
        ImageStore.shared.image(name: imageName)
    }
}

struct Coordinates: Hashable, Codable {
    var latitude: Double
    var longitude: Double
}
````

## フレームワークのインポート
`SwiftUI` フレームワークは、`Image` ビューを扱うためにインポートされています。
`CoreLocation` は座標系を扱うためにインポートされています。

````Swift:Landmark.swift
import SwiftUI
import CoreLocation
````

## Coordinates 構造体
緯度を扱う変数 `latitude` と経度を扱う変数 `longitude` が宣言されいるだけです。
共に、座標系のデータ型ではなく、シンプルな `Double` 型になっています。

````Swift:Landmark.swift
struct Coordinates: Hashable, Codable {
    var latitude: Double
    var longitude: Double
}
````
構造体が、2つのプロトコル `Hashable`, `Codable` に準拠している点に注意です。

## Landmark 構造体
このファイルの本体となっている部分で、１つの観光地を表現する型です。
やはり、`Hashable` と `Codable` に準拠しています。

````Swift:Landmark.swift
struct Landmark: Hashable, Codable {
    var id: Int
    var name: String
    fileprivate var imageName: String
    fileprivate var coordinates: Coordinates
    var state: String
    var park: String
    var category: Category

    var locationCoordinate: CLLocationCoordinate2D {
        CLLocationCoordinate2D(
            latitude: coordinates.latitude,
            longitude: coordinates.longitude)
    }

    enum Category: String, CaseIterable, Codable, Hashable {
        case featured = "Featured"
        case lakes = "Lakes"
        case rivers = "Rivers"
    }
}
````

### プロパティ

````Swift:Landmark構造体のメンバープロパティ
var id: Int
var name: String
fileprivate var imageName: String
fileprivate var coordinates: Coordinates
var state: String
var park: String
var category: Category
var locationCoordinate: CLLocationCoordinate2D {
    CLLocationCoordinate2D( latitude: coordinates.latitude,
                            longitude: coordinates.longitude)
}
````
プロパティとして、8つの変数（うち、１つは計算プロパティ）が宣言されています。
注目すべきプロパティは、`imageName` です。
この文字列を基に、画像データを取得することになります。
また、観光地を区分するための列挙型 `Category` も定義されています。

この時点で不思議なのは、`coordinates` と `locationCoordinate` の違いです。
どちらも座標系を表現していますが、`coordinates` はカスタム構造体で `locationCoordinate` は `CLLocationCoordinate2D`型 を返す計算プロパティになっています。
チュートリアルを進めていけば、それぞれの役割が理解できると思われます。



## Landmark エクステンション
観光地の画像データが割り当てられる変数 `image` があります。
計算プロパティになっており、アクセスがあるたびに画像を返します。
シングルトンパターンによって、 `ImageStore` インスタンスの型プロパティ `shared` から `image(name:)` メソッドを呼び出しています。

````Swift:Landmark.swift
extension Landmark {
    var image: Image {
        ImageStore.shared.image(name: imageName)
    }
}
````