ios – Get data from model for multiple List views ObservableObject class and App Storage to save for both list

0
188


How to pull in the data from MenuListItemModel.swift ObservableObject classes to load into FriendshipListView.swift and WealthListView.swift. The WealthListView.swift is loading the same data as FriendshipListView.swift. Also, do I have to do something with @AppStorage so each list saves the states properly?

MenuApp.swift

import SwiftUI

@main
struct ManifestationMenuApp: App {
    
    @AppStorage("isOnboarding") var isOnboarding: Bool = true
    
    var body: some Scene {
        WindowGroup {
            if isOnboarding {
                OnboardingView()
            } else {
                MainView()
                    .environmentObject(MenuListFriendshipModel())
                    .environmentObject(MenuListWealthModel())
            }
        }
    }
}

MenuListItemModel.swift

import SwiftUI

struct MenuListItemModel: Identifiable, Codable {
    var id: String = UUID().uuidString
    var title: String
    var description: String
    var isCompleted: Bool
}

MenuListFriendshipModel.swift

import SwiftUI

//use array in @Appstorage
extension Array: RawRepresentable where Element: Codable{
    public init?(rawValue: String) {
            guard let data = rawValue.data(using: .utf8),
                  let result = try? JSONDecoder().decode([Element].self, from: data)
            else {
                return nil
            }
            self = result
        }

        public var rawValue: String {
            guard let data = try? JSONEncoder().encode(self),
                  let result = String(data: data, encoding: .utf8)
            else {
                return ""
            }
            return result
        }
    
}

class MenuListFriendshipModel: ObservableObject {
    // this loads and saves the items automatic to UserDefaults
    @AppStorage("task_items_list") var items: [MenuListItemModel] = []
    
    
    init() {
        // fill the collection only if it is empty
        if items.isEmpty{
            myTaskItems()
        }
    }
    
    func myTaskItems() {
        items = [
            MenuListItemModel(title: "I am grateful to have close and meaningful relationships.", description: "My relationships are healthy and enduring, whether with friends, colleagues, family, or romantic contacts.", isCompleted: false),
            MenuListItemModel(title: "My relationships are fun and rewarding", description: "(e.g., exciting, generous, etc.) ",isCompleted: false),
            MenuListItemModel(title: "No matter how long my relationships last, they are experiences I cherish.", description: "Thirty years or thirty minutes, my relationships are not judged on how long they last but on their meaningful moments.",isCompleted: false),
            MenuListItemModel(title: "I treat my friends as I wish them to treat me.", description: "I am grateful for the wisdom to know when my friends and loved ones need my understanding, advice, or ears.",isCompleted: false),
            MenuListItemModel(title: "I have a few friends whom I love.", description: "I realize how fortunate I am to have a few close friends who are always by my side through good and bad times.",isCompleted: false),
            MenuListItemModel(title: "My friends are great at finding new ways for us to be together. ", description: "We are never out of ideas on how to create excellent and meaningful moments together.",isCompleted: false),
            MenuListItemModel(title: "I am fine without relationships.", description: "I do not shun relationships, but I do not find them necessary for a meaningful life.",isCompleted: false),
            MenuListItemModel(title: "I am open to making new friends.", description: "Each new friend is a new world to discover; the more, the merrier.",isCompleted: false)
        ]
        
    }
}

class MenuListWealthModel: ObservableObject {
    // this loads and saves the items automatic to UserDefaults
    @AppStorage("task_items_list") var items: [MenuListItemModel] = []
    
    
    init() {
        //fill the collection only if it is empty
        if items.isEmpty{
            myTaskItems()
        }
    }
    
    func myTaskItems() {
        items = [
            MenuListItemModel(title: "Test", description: "testing",isCompleted: false),
            MenuListItemModel(title: "Test", description: "testing",isCompleted: false),
            MenuListItemModel(title: "Test", description: "testing",isCompleted: false),
            MenuListItemModel(title: "Test", description: "testing",isCompleted: false),
            MenuListItemModel(title: "Test", description: "testing",isCompleted: false),
            MenuListItemModel(title: "Test", description: "testing",isCompleted: false),
            MenuListItemModel(title: "Test", description: "testing",isCompleted: false),
            MenuListItemModel(title: "Test", description: "testing",isCompleted: false)
        ]
        
    }
}

MenuListRowView.swift

import SwiftUI

struct MenuListRowView: View {
    // This binding will assure changes will bubble up into the ViewModel represents the state of model data that will be saved in UserDefaults
    
    @Binding var item: MenuListItemModel
    
    var body: some View {
        HStack(alignment: .top) {
            Image(systemName: item.isCompleted ? "checkmark.circle" : "circle") //.imageScale(.large)
                .foregroundColor(item.isCompleted ? .green : .gray)
                .font(.system(size: 30, weight: .bold))
                .padding(.top, 6)
            VStack(alignment: .leading, spacing: 8) {
                Text(item.title)
                    .font(.title3.bold())
                Text(item.description)
                    .font(.body)
            }
            Spacer()
        }
        .padding(.vertical, 8)
        .onTapGesture {
            item.isCompleted.toggle()
        }
    }
}

FriendshipListView.swift

import SwiftUI

struct FriendshipListView: View {
    
    @EnvironmentObject var listViewModel: MenuListFriendshipModel
    
    var body: some View {
        NavigationView {
            List {
                //Use the $ syntax to pass a binding on to the subviews
                ForEach($listViewModel.items) { $item in
                    MenuListRowView(item: $item)
                }
            }
            .navigationBarTitle(Text("Friendships / Relationships"))
            .listStyle(PlainListStyle())
        }
    }
}

struct ListView_Previews: PreviewProvider {
    static var previews: some View {
        FriendshipListView()
        .environmentObject(MenuListFriendshipModel())
    }
}

WealthListView.swift

import SwiftUI

struct WealthListView: View {
    
    @EnvironmentObject var listViewModel: MenuListWealthModel
    
    var body: some View {
        NavigationView {
            List {
                //Use the $ syntax to pass a binding on to the subviews
                ForEach($listViewModel.items) { $item in
                    MenuListRowView(item: $item)
                }
            }
            .navigationBarTitle(Text("Money / Wealth / Security"))
            .listStyle(PlainListStyle())
        }
    }
}

struct WealthListView_Previews: PreviewProvider {
    static var previews: some View {
        WealthListView()
        .environmentObject(MenuListWealthModel())
    }
}

FriendListView

WealthListView