Monday, October 3, 2022
HomeiOS Developmentios - How would I get persistent data to work in my...

ios – How would I get persistent data to work in my app?

[ad_1]

I tried to implement persistent data in my app but when I close out my app and re open it none of the reminders that were created were saved. Does anyone know how I would be able to fix this. I have my ReminderStore, HomeView, NextUpApp, and HomeViewModel listed below. at the bottom of HomeView there is an onChange modifier so the app knows to save the users actions(reminders) when the app is inactive.

Reminder

”’

struct Reminder: Identifiable, Equatable, Codable {
var title: String
var notes: String?
var date: Date?
var time: Date?
var theme: Theme
var iscomplete: Bool
var priority: RemindPriority
let id: UUID
//let filter: FilterType

init(title: String, notes: String? = nil, date: Date? = nil, time: Date? = nil, theme: Theme, iscomplete: Bool = false, priority: RemindPriority = .None, id: UUID = UUID()) {
    self.title = title
    self.notes = notes
    self.date = date
    self.time = time
    self.theme = theme
    self.iscomplete = iscomplete
    self.priority = priority
    self.id = id
}

”’

ReminderStore

”’

import Foundation
import SwiftUI

class ReminderStore: ObservableObject {
@Published var reminds: [Reminder] = []

private static func fileURL() throws -> URL {
    try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
        
        .appendingPathComponent("reminds.data")
}

static func load(completion: @escaping (Result<[Reminder], Error>) -> Void) {
    DispatchQueue.global(qos: .background).async {
        do {
            let fileURL = try fileURL()
            guard let file = try? FileHandle(forReadingFrom: fileURL) else {
                DispatchQueue.main.async {
                    completion(.success([]))
                }
                return
            }
            let reminders = try JSONDecoder().decode([Reminder].self, from: file.availableData)
            DispatchQueue.main.async {
                completion(.success(reminders))
            }
        } catch {
            DispatchQueue.main.async {
                completion(.failure(error))
            }
        }
    }
}

static func save(reminds: [Reminder], completion: @escaping (Result<Int, Error>) -> Void) {
    DispatchQueue.global(qos: .background).async {
        do {
            let data = try JSONEncoder().encode(reminds)
            let outfile = try fileURL()
            try data.write(to: outfile)
            DispatchQueue.main.async {
                completion(.success(reminds.count))
            }
        } catch {
            DispatchQueue.main.async {
                completion(.failure(error))
            }
        }
    }
}  
}

”’

HomeView

”’

import SwiftUI

struct HomeView: View {
@StateObject var homeVM: HomeViewModel
@Environment(\.scenePhase) private var scenePhase
@State var percent: Int = 1
@State var showDetailEditView = false
@State var showAddView = false
@State var dropDown = false
@State var index: Int?
@ObservedObject private var notificationManager = LocalNotificationManager()
let saveAction: ()->Void


//@State var filter = false

var body: some View {
        ZStack {
            List {
                ForEach($homeVM.reminds) { $remind in
                    NavigationLink(destination: ReminderDetailView(remindVM: ReminderViewModel(remind: $remind))) {
                        ReminderView(remind: $remind)
                    }
                        .listRowBackground(remind.theme.mainColor)
                        .buttonStyle(PlainButtonStyle())
                        .listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0))
                        .swipeActions(edge: .leading) {
                            Button(action: {
                                self.showDetailEditView.toggle()
                                homeVM.existingRemindData = remind.data
                                index = homeVM.reminds.firstIndex(of: remind)
                            }) {
                                Label("Edit", systemImage: "pencil")
                            }
                        }
                        .sheet(isPresented: $showDetailEditView, onDismiss: {homeVM.existingRemindData = Reminder.Data()}) {
                            NavigationView {
                                ReminderEditView(data: $homeVM.existingRemindData)
                                    .navigationTitle(homeVM.existingRemindData.title)
                                    .toolbar {
                                        ToolbarItem(placement: .cancellationAction) {
                                            Button("Cancel") {
                                                self.showDetailEditView.toggle()
                                                homeVM.existingRemindData = Reminder.Data()
                                            }
                                        }
                                        ToolbarItem(placement: .confirmationAction) {
                                            Button("Done") {
                                                self.showDetailEditView.toggle()
                                                homeVM.reminds[index!].update(from: homeVM.existingRemindData)
                                                if homeVM.reminds.last?.data.date != nil {
                                                    notificationManager.deleteLocalNotifications(identifiers: [homeVM.reminds[index!].id.uuidString])
                                                    notificationManager.sendNotification(date: (homeVM.reminds.last?.data.combineDateWithTime(date: (homeVM.reminds.last?.data.date)!, time: homeVM.reminds.last?.data.time ?? Calendar(identifier: .gregorian).date(bySettingHour: 0, minute: 0, second: 0, of: Date())!))!, type: "date", title: (homeVM.reminds.last?.title)!, body: (homeVM.reminds.last?.notes) ?? "", id: (homeVM.reminds.last?.id)!)
                                                        print(Calendar(identifier: .gregorian).date(bySettingHour: 0, minute: 0, second: 0, of: Date())!)
                                                    //print(notificationManager.notifications)
                                                    //print((homeVM.reminds.last?.id)!)
                                                }
                                                homeVM.newRemindData = Reminder.Data()
                                            }
                                        }
                                    }
                                    .background(LinearGradient(gradient: Gradient(colors: [
                                        Color(UIColor(red: 0.376, green: 0.627, blue: 0.420, alpha: 1)),
                                        Color(UIColor(red: 0.722, green: 0.808, blue: 0.725, alpha: 1))
                                    ]), startPoint: .topLeading, endPoint: .bottomTrailing))
                            }
                        }
                        .swipeActions(allowsFullSwipe: true) {
                            Button (role: .destructive, action: {
                                homeVM.deleteReminder(remind: remind)
                                notificationManager.deleteLocalNotifications(identifiers: [remind.id.uuidString])
                                print("\(notificationManager.deletedNotifications.count) 3")
                            }) {
                                Label("Delete", systemImage: "trash.fill")
                            }
                        }
                }
            }
            .onAppear(
                perform: {
                    UITableView.appearance().backgroundColor = .clear
                    UITableViewCell.appearance().backgroundColor = .clear
                })
            .safeAreaInset(edge: .top) {
                HStack {
                    /*
                    Button(action: {
                        self.filter.toggle()
                    }) {
                        Image(systemName: "line.3.horizontal")
                            .font(.system(size: 25))
                    }
                    
                    Spacer()
                    
                    HStack {
                        Text("Hello")
                        .font(.largeTitle.bold())
                        Image(systemName: "chevron.right")
                            .font(.system(size: 17, weight: .bold, design: .default))
                            .frame(width: 10, height: 10, alignment: .center)
                            .onTapGesture {
                                self.dropDown.toggle()
                            }
                            .rotationEffect(dropDown ? .degrees(90) : .degrees(0))
                            .animation(Animation.easeInOut(duration: 0.2), value: dropDown)
                    }
                    */
                    
                    Text("NextUp \(homeVM.reminds.count)")
                        .font(.largeTitle.bold())
                    
                    Spacer()
                    Button(action: {
                        self.showAddView.toggle()
                    }) {
                        Image(systemName: "plus")
                            .font(.system(size: 25))
                    }
                    .sheet(isPresented: $showAddView, onDismiss: {homeVM.newRemindData = Reminder.Data()}) {
                        NavigationView {
                            ReminderEditView(data: $homeVM.newRemindData)
                            .toolbar {
                                ToolbarItem(placement: .cancellationAction) {
                                    Button("Dismiss") {
                                        showAddView = false
                                        homeVM.newRemindData = Reminder.Data()
                                    }
                                }
                                ToolbarItem(placement: .confirmationAction) {
                                    Button("Add") {
                                        homeVM.newReminder()
                                        
                                        if homeVM.reminds.last?.data.date != nil {
                                            notificationManager.sendNotification(date: (homeVM.reminds.last?.data.combineDateWithTime(date: (homeVM.reminds.last?.data.date)!, time: homeVM.reminds.last?.data.time ?? Calendar(identifier: .gregorian).date(bySettingHour: 0, minute: 0, second: 0, of: Date())!))!, type: "date", title: (homeVM.reminds.last?.title)!, body: (homeVM.reminds.last?.notes) ?? "", id: (homeVM.reminds.last?.id)!)
                                            print(Calendar(identifier: .gregorian).date(bySettingHour: 0, minute: 0, second: 0, of: Date())!)
                                            //print(notificationManager.notifications)
                                            //print((homeVM.reminds.last?.id)!)
                                            
                                            
                                        }
                                        showAddView = false
                                    }
                                }
                            }
                            .background(LinearGradient(gradient: Gradient(colors: [
                                Color(UIColor(red: 0.376, green: 0.627, blue: 0.420, alpha: 1)),
                                Color(UIColor(red: 0.722, green: 0.808, blue: 0.725, alpha: 1))
                            ]), startPoint: .topLeading, endPoint: .bottomTrailing))
                            .navigationTitle("New Reminder")
                        }
                    }
                }
                .padding()
                .background(Color.clear.overlay(.ultraThickMaterial))
            }
            .safeAreaInset(edge: .bottom) {
                ForEach(homeVM.reminds) { remind in
                    if remind.iscomplete {
                        ProgressBarView(progress: Float(homeVM.compReminds.count) / Float(homeVM.reminds.count))
                                .padding(.vertical)
                                .onAppear {
                                    homeVM.appendRemind(complete: remind)
                                }
                                .onDisappear {
                                    homeVM.removeRemind(remind: remind)
                                }
                    }
                    
                }
                .frame(height: 75)
                .background(Color.white.overlay(.ultraThickMaterial))
            }
            .ignoresSafeArea(edges: .bottom)
            .background(LinearGradient(gradient: Gradient(colors: [
                Color(UIColor(red: 0.376, green: 0.627, blue: 0.420, alpha: 1)),
                Color(UIColor(red: 0.722, green: 0.808, blue: 0.725, alpha: 1))
            ]), startPoint: .topLeading, endPoint: .bottomTrailing)
                )
        .navigationBarHidden(true)
        .onChange(of: scenePhase) { phase in
            if phase == .inactive { saveAction() }
        }

”’

NextUpApp

”’

import SwiftUI

@main
struct NextUpApp: App {
//@State private var reminds = Reminder.sampleReminders
@StateObject private var store = ReminderStore()

var body: some Scene {
    WindowGroup {
        NavigationView {
            HomeView(homeVM: HomeViewModel(reminds: store.reminds)) {
                ReminderStore.save(reminds: store.reminds) { result in
                    if case .failure(let error) = result {
                        fatalError(error.localizedDescription)
                    }
                }
            }
        }
        .onAppear {
            ReminderStore.load { result in
                switch result {
                case .failure(let error):
                    fatalError(error.localizedDescription)
                case .success(let reminds):
                    store.reminds = reminds
                    //print("Works")
                }
            }
        }
    }
}
}

”’

HomeViewModel

”’

import Foundation
import SwiftUI
import Combine

class HomeViewModel: ObservableObject {
@Published var reminds: [Reminder]
@Published var newRemindData = Reminder.Data()
@Published var existingRemindData = Reminder.Data()
@Published var selectedRemind = Reminder(data: Reminder.Data())
@Published var compReminds: [Reminder] = []

private var cancellables = Set<AnyCancellable>()

init(reminds: [Reminder]) {
    self.reminds = reminds
}

func newReminder() {
    let newRemind = Reminder(data: newRemindData)
    reminds.append(newRemind)
    newRemindData = Reminder.Data()
}

func deleteReminder(remind: Reminder) {
    Just(remind)
        .delay(for: .seconds(0.25), scheduler: RunLoop.main)
        .sink {remind in
            if remind.iscomplete {
                self.removeRemind(remind: remind)
            }
            if !remind.iscomplete {
                
                self.removeRemind(remind: remind)
            }
            self.reminds.removeAll { $0.id == remind.id }
        }
        .store(in: &cancellables)
}

func appendRemind(complete: Reminder) {
    compReminds.append(complete)
}

func removeRemind(remind: Reminder) {
    compReminds.removeAll() { $0.id == remind.id }
}

func remindIndex() -> Int {
    return reminds.firstIndex(where: {
        $0.id == existingRemindData.id
    }) ?? 1
}
}

”’

[ad_2]

Source link

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments