解放区在住氷翠 緑の閃光
【解放区在住氷翠 緑の閃光】swift

【SwiftUI】クラスを使ってリストを作ってみる

2018-05-27 23:20

このページの環境は
Swiftをベースにしています。
また、開発環境はXcode14.1
MacosVetura 13.0.1となります。

氷翠です。

今回は「リスト表示を作ってみる【SwiftUI】」で作成したリストのアプリを使って、更に外部というか、他のファイルを用意、クラスを作成してデータを作成してリストにすることが目的となります。

まずは前回と同じプログラムをコピーw

import SwiftUI

struct ContentView: View {
    var body: some View {
        VStack {
            HStack(alignment: .bottom, spacing: -2.0) {
                Text("ファイル数")
                Spacer()
                Text("000本")
            }
            .padding(10.0)
            Divider()
            List {
                fileListView(fileName: "テスト_001.txt", midashi: "見出し 1")
                fileListView(fileName: "テスト_002.txt", midashi: "見出し 2")
                fileListView(fileName: "テスト_003.txt", midashi: "見出し 3")
                fileListView(fileName: "テスト_004.txt", midashi: "見出し 4")
                fileListView(fileName: "テスト_005.txt", midashi: "見出し 5")
                fileListView(fileName: "テスト_006.txt", midashi: "見出し 6")
                fileListView(fileName: "テスト_007.txt", midashi: "見出し 7")
                fileListView(fileName: "テスト_008.txt", midashi: "見出し 8")
                fileListView(fileName: "テスト_009.txt", midashi: "見出し 9")
                fileListView(fileName: "テスト_010.txt", midashi: "見出し 10")
            }
            .frame(width: 300.0)
            .listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0))
        }
        .frame(width: 300.0)
    }
}
import SwiftUI

struct fileListView: View {
    
    var fileName: String
    var midashi: String
    
    var body: some View {
        VStack {
            HStack {
                Image(systemName: "doc.text.fill")
                    .padding(.horizontal, 5.0)
                VStack(alignment: .leading) {
                    Text("\(fileName)")
                        .font(.title3)
                        .multilineTextAlignment(.leading)
                    Divider()
                        .padding(.vertical, -4.0)
                        .foregroundColor(.black)
                    Text("\(midashi)")
                        .font(.caption)
                        .multilineTextAlignment(.leading)
                }
                Spacer()
                Image(systemName: "chevron.right.circle.fill")
                    .padding(.horizontal, 5.0)
            }
        }
        .padding(.horizontal, 0.0)
        Divider()
            .foregroundColor(.gray)
    }
}

struct fileListView_Previews: PreviewProvider {
    static var previews: some View {
        fileListView(fileName: "テスト.txt", midashi: "見出し見出し")
    }
}

デザイン的にはこれで。
ここから別のファイル「dataModel.swift」を用意する。

import Foundation

// データの形を決める(一個分)
struct dataModel: Identifiable {
    var id       = UUID() // ユニークなIDを自動でつけていく
    var fileName : String // ファイル名
    var midashi  : String // 見出し
}

// 実際のデータを作成するためのクラスを作成する
class dataReadyModel: ObservableObject {
    
    var data: [dataModel] = []
    
    init() {
        for i in 0 ..< 20 { // 配列の要素の数は全部で20個を予定
            let a = dataModel(
                fileName: "ファイル名_" + String(i),
                midashi: "見出し " + String(i)
            )
            self.data.append(a) // 配列変数にデータを追加していく
        }
    }
}

上のプログラムで全部です。
「dataModel」というstructを準備。「Identifiable」を利用しておく。これを使うことでユニークIDを利用することができる。さらに、今回のような場合、IDを用意することでスムーズにリスト化することができるようだ。

で、その下のクラス。このクラスには「ObservableObject」を追加しておく。

データ自体は単純な配列変数で同じようなデータを繰り返し保管しておくつもりなので、「var data: [dataModel] = []」この変数定義一つで十分。

あとは「init()」メソッドで初期設定。この時点でデータを用意してあげればよい。

ここで「ContentView.swift」に戻る。つまりはメインのプログラムの方。
上では「List{}」の中にデータを用意したのだけど、この後ではさらにデータを自動で読み込んで繰り返し処理によって表示させるという処理。

import SwiftUI

struct ContentView: View {
    
    // データを動的に表示させるためにクラスからデータを取り込む
    @State private var data = dataReadyModel().data
    
    var body: some View {
        VStack {
            HStack(alignment: .bottom, spacing: -2.0) {
                Text("ファイル数")
                Spacer()
                Text("\(data.count)本")
            }
            .padding(10.0)
            Divider()
            List {
                // 取り込んだデータを元にリストとして繰り返し処理を行う
                ForEach(data, id: \.id) { i in // i の中に要素が入っていくことになる
                    fileListView(fileName: i.fileName, midashi: i.midashi)
                }
            }
            .frame(width: 300.0)
            .listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0))
        }
        .frame(width: 300.0)
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

まず「body」の上に変数を定義。このデザインの中で利用する変数です。
このファイルの中ではデータを用意するとかそういうのは禁止事項になるので、「@State private var data = dataReadyModel().data」という感じでデータをあらかじめ用意してあげます。ちなみに、データは都度変更することができるので、「動的な変数」ということになります。

で、「List{}」の中はForEachでデータを繰り返す処理。その中でListの中は別のファイルで定義したデザインに動的な変数を次々に渡していくという感じになります。

他でもこういった変数の使い方でいろんな場面で役に立つ。

ということで、今回はここまで。