[SwiftUI] 複数セクションがあるリスト

2つのセクション

struct ContentView: View {
    let shikoku = ["徳島県","香川県","愛媛県","高知県"]
    let kyushu = ["福岡県","佐賀県","長崎県","熊本県","大分県","宮崎県","鹿児島県"]
    
    var body: some View {
        List {
            Section(header: Text("四国").font(.largeTitle).padding(.top),
                    footer: Text("最高標高は石鎚山の1982m")){
                ForEach(shikoku, id:\.self){ item in
                    Text(item)
                }
            }
            Section(header: Text("九州").font(.largeTitle).padding(.top),
                    footer: Text("最高標高は宮之浦岳の19,36m")){
                ForEach(kyushu, id:\.self){ item in
                    Text(item)
                }
            }
        }
    }
}

InsetGroupListStyle, GroupListStyle, InsetListStyle, PlainListStyle, SidebarListStyle, SidebarListStyleなどがある

### 行に表示するビューを定義
Assetに写真を入れ、PhotoData.swiftを作成

PhotoData.swift

import Foundation

struct PhotoData: Identifiable {
    var id = UUID()
    var imageName:String
    var title:String
}

var photoArray = [
    PhotoData(imageName:"IMG_0996", title: "湘南平展望レストランFlat"),
    PhotoData(imageName:"IMG_1035", title: "アウトリガーカヌー"),
    PhotoData(imageName:"IMG_1504", title: "えぼし号"),
    PhotoData(imageName:"IMG_1531", title: "富士山"),
    PhotoData(imageName:"IMG_2139", title: "DENTAL CLINIC"),
    PhotoData(imageName:"IMG_2250", title: "鵠沼漁港白灯台"),
    PhotoData(imageName:"IMG_2269", title: "サザンビーチ海の家"),
    PhotoData(imageName:"IMG_2470", title: "天使の翼"),
    PhotoData(imageName:"IMG_2883", title: "スイミングスクールバス"),
    PhotoData(imageName:"IMG_4199", title: "小田急線江ノ島駅"),
    PhotoData(imageName:"IMG_6460", title: "鷹取山"),
    PhotoData(imageName:"IMG_7122", title: "支笏湖ぼスワンボート"),
    PhotoData(imageName:"IMG_7216", title: "とまチョップ"),
    PhotoData(imageName:"IMG_7745", title: "スナックJunko"),
    PhotoData(imageName:"IMG_7851", title: "山の電話ボックス")
]

RowView.swift
  L RowView_Previews: PreviewProviderで一行だけのレイアウトを確認できる

import SwiftUI

struct RowView: View {
    var photo:PhotoData
    var body: some View {
        HStack {
            Image(photo.imageName)
                .resizable()
                .frame(width: 60, height: 60)
                .clipShape(Circle())
                .overlay(Circle().stroke(Color.gray))
            Text(photo.title)
            Spacer()
        }
        
    }
}
struct RowView_Previews: PreviewProvider {
    static var previews: some View {
        RowView(photo:photoArray[0])
            .previewLayout(.sizeThatFits)
    }
}

ContentView.swift
L identifiableプロトコルを採用した構造体であればphotoArrayを利用できる
L idはidentifiableプロトコルが指定するプロパティ
  L PhotoData.swiftのphotoArrayはアクセス権がinternalの為、アクセスできる

struct ContentView: View {
    var body: some View {
        List(photoArray){ item in
            RowView(photo: item)
        }
    }
}

### リストから詳細ページを開く

struct PhotoDetailView: View {
    var photo:PhotoData
    
    var body: some View {
        VStack {
            Image(photo.imageName)
                .resizable()
                .aspectRatio(contentMode: .fit)
            Text(photo.title)
            Spacer()
        }
        .padding()
    }
}

struct PhotoDetailView_Previews: PreviewProvider {
    static var previews: some View {
        PhotoDetailView(photo:photoArray[0])
    }
}

詳細ページへの移動

struct ContentView: View {
    var body: some View {
        NavigationView {
            List(photoArray){ item in
                NavigationLink(destination: PhotoDetailView(photo: item)){
                    RowView(photo: item)
                }
            }
            .navigationTitle(Text("写真リスト"))
        }
    }
}

### 構造体
struct ContentViewは ContentView構造体を定義している

struct Member {
    let name:String
    var level = 1
    var age:Int
}

var member1 = Member(name: "鈴木", age: 19)
var member2 = Member(name: "田中", level: 5, age: 23)

let text1 = "\(member1.name)さん \(member1.age)歳 レベル \(member1.level)"
print(text1)

構造体イニシャライザ
  L selfはプロパティを指す

struct Box {
    let width: Int
    let height: Int
    let size: String
    
    init(width:Int, height:Int){
        self.width = width
        self.height = height
        if(width+height)<120 {
            size = "M"
        } else {
            size = "L"
        }
    }
}
let box1 = Box(width: 50, height: 50)
let box2 = Box(width: 40, height: 100)
print(box1)
print(box2)

プロトコルが指定してある構造体はプロパティやメソッドが定まっている

### ユーザ関数
戻り値の型を指定する

func calc(adult:Int, child:Int) -> Int {
    let money = adult * 1200 + child * 500
    return money
}

let price = calc(adult: 3, child: 2)
print(price)

引数の初期値を設定

func calc2(adult:Int = 0, child:Int = 0) -> Int {
    let money = adult * 1200 + child * 500
    return money
}

let adult1 = calc2(adult: 1)
let child2 = calc2(child: 2)
print(adult1)
print(child2)

値を返さない関数
L returnがなく、戻り値をvoidにするか、-> Voidを省略できる

import UIKit

var isPlay = false

func play() -> Void {
    isPlay = true
}
play()
print(isPlay)

構造体やinternalの意味がわかったわ
swiftを勉強すると、他の静的型付け言語の理解にもつながるね