SwiftUI – List 2 Filter

Filtered List

This example is inspired by Apple Documentation (Handling User Input)

This sample covered

  • How to use Toggle (More details please check SwiftUI – Toggle Switch
  • ForEach in SwiftUI
  • @EnvironmentObject
  • Filter (Logic)
  • NavigationLink
  • Button

List with @EnvironmentObject

Let’s check ListView code first.

import SwiftUI

struct FilterListView: View {
    
    @EnvironmentObject private var userData : UserData
    
    var body: some View {
        NavigationView {
            List {
                Toggle(isOn: $userData.showFavoritesOnly) {
                    Text("Show Favorite Only")
                }
                ForEach(userData.shikuyorolist) { item in
                    if !self.userData.showFavoritesOnly || item.favorite {
                        NavigationLink(destination: ToggleDetailView(item: item).environmentObject(self.userData)) {
                            ItemWithStarRow(item: item)
                        }
                    }
                }
            }
        }
        .navigationBarTitle(Text("List"))
    }
}

struct FilterListView_Previews: PreviewProvider {
    static var previews: some View {
        FilterListView().environmentObject(UserData())
    }
}

As I explained last entry, @EnvironmentObject is managed data between multiple views. We can pass this from other views etc…

Check UserData

UserData.swift

import Foundation

final class UserData: ObservableObject {
    
    @Published var showFavoritesOnly = false
    
    @Published var shikuyorolist : [FavoriteItem] = [
        FavoriteItem(id: 1, name: "shikuyoro", imageName: "shikuyoro", time: "2020/06/09 12:00", favorite: true),
        FavoriteItem(id: 2, name: "shikuyoro", imageName: "shikuyoro", time: "2020/06/11 23:00", favorite: false)
    ]
}

ObservableObject is as it is. In Android, there is similar concept. ObservableObject.

@Published is needed to apply observable.

So, this class is changeable and monitored by views.

Next, check NavigationLink destination

ToggleDetailView.swift

import SwiftUI

struct ToggleDetailView: View {
    
    @EnvironmentObject var userData: UserData
    
    var item : FavoriteItem
    
    var index: Int {
        userData.shikuyorolist.firstIndex(where: { $0.id == item.id })!
    }
    
    var body: some View {
        VStack {
            Image(item.imageName)
            .clipShape(Circle())
                .overlay(Circle().stroke(Color.white, lineWidth: 4))
            .shadow(radius: 10)
            .scaledToFit()
            Spacer()
            Button(action: {
                self.userData.shikuyorolist[self.index]
                    .favorite.toggle()
            }) {
                if self.userData.shikuyorolist[self.index]
                    .favorite {
                    Image(systemName: "star.fill")
                        .foregroundColor(Color.yellow)
                } else {
                    Image(systemName: "star")
                        .foregroundColor(Color.gray)
                }
            }
        }
    }
}

struct ToggleDetailView_Previews: PreviewProvider {
    static var previews: some View {
        let userData = UserData()
        return ToggleDetailView(item: userData.shikuyorolist[0])
        .environmentObject(userData)
    }
}

This View also has @EnvironmentObject passed by parent view.

And this view has button. Press button and change UserData. UserData is observable and change here and update parent view data, too.

Finally, how to use this in SceneDelegate

SceneDelegate.swift

This is not full code. Only important point

let contentView = FilterListView().environmentObject(UserData())
iOS
スポンサーリンク
Professional Programmer2

コメント