100 Days of SwiftUI(DAY 68(Project14 part 1))

バケットリスト:はじめに
Bucket List: Introduction

このプロジェクトでは、ユーザーが1日に訪問する予定の地図上の場所のプライベートリストを作成し、その場所の説明を追加し、近くにある興味深い場所を検索して保存できるアプリを作成しますすべてを後でiOSストレージに保存します。

これらすべてを機能させるには、フォーム、シート、、など、すでに習得したスキルを活用するだけでなく、SwiftUIアプリにマップを埋め込む方法、プライベートデータを安全に保存する方法CodableなどURLSession、いくつかの新しいスキルについても説明します認証されたユーザーのみがアクセスでき、外部でデータをロードおよび保存する方法UserDefaultsなどがあります。

コーディネーターを使用してSwiftUI手段に地図を埋め込みます。

カスタムタイプのComparableへの適合の追加
Adding conformance to Comparable for custom types

Comparableの定義に準拠を追加しUserます。

import SwiftUI

//struct User: Identifiable {
//    let id = UUID()
//    let firstName: String
//    let lastName: String
//}
struct User: Identifiable, Comparable {
    let id = UUID()
    let firstName: String
    let lastName: String

    static func < (lhs: User, rhs: User) -> Bool {
        lhs.lastName > rhs.lastName
    }
}

struct ContentView: View {
    let users = [
        User(firstName: "Arnold", lastName: "Rimmer"),
        User(firstName: "Kristine", lastName: "Kochanski"),
        User(firstName: "David", lastName: "Lister"),
    ].sorted()
    
    var body: some View {
        List(users) { user in
            Text("\(user.lastName), \(user.firstName)")
        }
    }
}

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

ドキュメントディレクトリへのデータの書き込み
Writing data to the documents directory

UserDefaults、へのデータの読み書き方法を確認しましたが、これはユーザー設定や少量のJSONに最適です。ただし、特に将来さらに多くのデータを保存する予定がある場合は、一般的にデータを保存するのに最適な場所ではありません。

このアプリでは、ユーザーが好きなだけデータを作成できるようにします。つまり、単に物事を投入UserDefaultsして最高のものを期待するよりも優れたストレージソリューションが必要です。さいわいなことに、iOSではデバイスストレージからのデータの読み取りと書き込みが非常に簡単になり、実際、すべてのアプリに必要なあらゆる種類のドキュメントを保存するためのディレクトリが作成されます。ここにあるファイルはiCloudバックアップと自動的に同期されるため、ユーザーが新しいデバイスを取得すると、データは他のすべてのシステムデータとともに復元されます。これについて考える必要すらありません。

import SwiftUI

struct ContentView: View {
    //---------------------------------
    func getDocumentsDirectory() -> URL {
        // find all possible documents directories for this user
        let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)

        // just send back the first one, which ought to be the only one
        return paths[0]
    }
    //---------------------------------
    var body: some View {
        Text("Hello World")
        .onTapGesture {
            let str = "Test Message"
            let url = self.getDocumentsDirectory().appendingPathComponent("message.txt")

            do {
                try str.write(to: url, atomically: true, encoding: .utf8)
                let input = try String(contentsOf: url)
                print(input)
            } catch {
                print(error.localizedDescription)
            }
        }
    }
}

挙型によるビューステートの切り替え
Switching view states with enums

条件付きビューが特に役立つのは、いくつかの異なる状態の1つを表示したい場合です。それを正しく計画すれば、ビューコードを小さく保つことができ、維持も容易になります。

Group {
    if Bool.random() {
        Rectangle()
    } else {
        Circle()
    }
}

import SwiftUI

struct ContentView: View {
    //---------------------------------
    enum LoadingState {
        case loading, success, failed
    }
    
    struct LoadingView: View {
        var body: some View {
            Text("Loading...")
            .bold()
        }
    }

    struct SuccessView: View {
        var body: some View {
            Text("Success!")
        }
    }

    struct FailedView: View {
        var body: some View {
            Text("Failed.")
        }
    }
    var loadingState = LoadingState.loading
    //---------------------------------
    var body: some View {
        Group {
            if loadingState == .loading {
                LoadingView()
            } else if loadingState == .success {
                SuccessView()
            } else if loadingState == .failed {
                FailedView()
            }
        }
        
    }
}