目的

Xcodeについて、新規プロジェクトを作成する際、デフォルトでSwiftUIが設定されるようになっていた。
(もちろんStoryBoardに戻すことも可能)

ということでSwiftUIをちょっとだけ勉強する目的で、テーブルViewでセルをタップすると詳細画面に遷移するだけのアプリを作成しようと思う。  
※SwiftUIでは、UITableViewではなくListと言うらしい。  

環境

  • Xcode Version 12.4
  • Swift 5

参照サイト

SwiftUI Essentials Building Lists and Navigation
上記のApple公式サイトの手順に沿って追加。  
このページでは上記をまとめているだけなので、不明点ありましたら、上記サイトを御覧ください。





SwiftUIアプリの作成

まずはXcodeでprojectを作成。   以下のようにSwiftUIが設定されているので、そのまま作成する。  
(ここでStoryBoardとかに変更できる)  

プロジェクトが作られると以下のようになる。  
フォルダ構成がかなりシンプル。  
AppDelegate.swiftとか無いし、いきなり戸惑う。

各種ファイルの作成

デフォルトで作られるContentViewは使わない。  

一覧・TaskList

import SwiftUI

struct TaskList: View {
    var body: some View {
        NavigationView {
            List(taskItems, id: \.id) { taskItem in
                NavigationLink(destination: TaskDetail(taskItem: taskItem)) {
                    TaskRow(taskItem: taskItem)
                }
            }
            .navigationTitle("Item")
        }
    }
}

struct TaskList_Previews: PreviewProvider {
    static var previews: some View {
        TaskList()
    }
}




セル・TaskRow

import SwiftUI

struct TaskRow: View {
    var taskItem: TaskItem
    
    var body: some View {
        HStack {
            Text(taskItem.title)
            Spacer()
        }
    }
}

struct TaskRow_Previews: PreviewProvider {
    static var previews: some View {
        TaskRow(taskItem: taskItems[1])
            .previewLayout(.fixed(width: 300, height: 70))
    }
}

詳細画面・TaskDetail

詳細画面
import SwiftUI

struct TaskDetail: View {
    var taskItem: TaskItem

    var body: some View {
        ScrollView {
            VStack(alignment: .leading) {
                Text(taskItem.title)
                    .font(.title)
                    .foregroundColor(.primary)

                .font(.subheadline)
                .foregroundColor(.secondary)

            }
            .padding()
        }
    }
}

struct LandmarkDetail_Previews: PreviewProvider {
    static var previews: some View {
        TaskDetail(taskItem: taskItems[1])
    }
}

TaskItem

構造体
import SwiftUI

struct TaskItem: Hashable, Codable {
    var id: Int
    var title: String
    
}

Modelの追加

表示するデータを追加する。  

Model
import Foundation

var taskItems: Array<TaskItem> = [TaskItem.init(id: 1, title: "a"),
                                  TaskItem.init(id: 2, title: "i"),
                                  TaskItem.init(id: 3, title: "u"),
                                  TaskItem.init(id: 4, title: "e"),
                                  TaskItem.init(id: 5, title: "o"),
                                  TaskItem.init(id: 6, title: "ka"),
                                  TaskItem.init(id: 7, title: "ki"),
                                  TaskItem.init(id: 8, title: "ku"),
                                  TaskItem.init(id: 9, title: "ke"),
                                  TaskItem.init(id: 10, title: "ko"),
                                  TaskItem.init(id: 11, title: "sa"),
                                  TaskItem.init(id: 12, title: "si"),
                                  TaskItem.init(id: 13, title: "su"),
                                  TaskItem.init(id: 14, title: "se"),
                                  TaskItem.init(id: 15, title: "so")]

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

メインファイルから

最後に最初からあるメインファイルからTableファイルの呼び出しを行う。

メインファイル
import SwiftUI

@main
struct tableApp: App {
    var body: some Scene {
        WindowGroup {
            TaskList()//この部分を変更
        }
    }
}

アプリの挙動





所感

すごい。簡単に組み込める。
あと各ファイルのPreviewProviderは画面右のPreviewの表示の役目だけのようで、機能的には不要な感じした。
ということは5,6クラスというのか構文というのか構造体というのか、
少し追加するだけTableView(リスト)が実現できた。

ただ自分は結構StoryBoardのシステムが好きだ。
初めての案件でアプリを触る場合は、UI ⇒ StoryBoard ⇒ classで解析したりする。

SwiftUIだとどうなるだろうか。。

ただ、SwiftUIはまだかなり未完成だと思った。
ここには書かなかったが、ViewControllerを使う場面もまだまだある。もちろんSwiftUIにViewControllerをコンバートすることもできる。
ViewControllerを使う場面としては、ライブラリのDelegateとかで。

以上。