article

Thursday, March 17, 2022

SwiftUI Note App UserDefaults

SwiftUI Note App UserDefaults

ContentView.swift
 
//
//  ContentView.swift
//  SwiftUIProject
//
//  Created by Cairocoders
//

import SwiftUI

struct ContentView: View {
    @StateObject var notes = Notes()
    @State private var sheetIsShowing = false
    
    var body: some View {
        NavigationView {
            VStack {
                NoteView()
                    .sheet(isPresented: $sheetIsShowing) {
                        AddNew()
                    }
            }
            .navigationTitle("Notes")
            .toolbar {
                ToolbarItem(placement: .navigationBarTrailing) {
                    Button {
                        withAnimation {
                            self.sheetIsShowing.toggle()
                        }
                    } label: {
                        Label("Add Note", systemImage: "plus.circle.fill")
                    }
                }
            }
        }
        .environmentObject(notes)
    }
    
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
NotesData.swift
 
//
//  NotesData.swift
//  SwiftUIProject
//
//  Created by Cairocoders
//

import Foundation
import SwiftUI

struct Note : Codable, Identifiable {
    var id = UUID()
    var title: String
    var content: String
    var timeStamp: String
}

@MainActor class Notes : ObservableObject {
    private let NOTES_KEY = "cairocodersnoteskey"
    let date = Date()
    var notes: [Note] {
        didSet {
            saveData()
            objectWillChange.send()
        }
    }
    
    init() {
        // Load saved data
        if let data = UserDefaults.standard.data(forKey: NOTES_KEY) {
            if let decodedNotes = try? JSONDecoder().decode([Note].self, from: data) {
                notes = decodedNotes
                return
            }
        }
        // Tutorial Note
        notes = [Note(title: "Test Note", content: "Tap add button. You can delete any note by swiping to the left!", timeStamp: date.getFormattedDate(format: "yyyy-MM-dd HH:mm:ss"))]
    }
    
    func addNote(title: String, content: String) {
        let tempNote = Note(title: title, content: content, timeStamp: date.getFormattedDate(format: "yyyy-MM-dd HH:mm:ss"))
        notes.insert(tempNote, at: 0)
        saveData()
    }
    
    // Save data
    private func saveData() {
        if let encodedNotes = try? JSONEncoder().encode(notes) {
            UserDefaults.standard.set(encodedNotes, forKey: NOTES_KEY)
        }
    }
}

extension Date {
   func getFormattedDate(format: String) -> String {
        let dateformat = DateFormatter()
        dateformat.dateFormat = format
        return dateformat.string(from: self)
    }
}
NoteView.swift
 
//
//  NoteView.swift
//  SwiftUIProject
//
//  Created by Cairocoders
//

import SwiftUI

struct NoteView: View {
    @EnvironmentObject var notes: Notes
    
    var body: some View {
        List {
            ForEach(notes.notes) { note in
                VStack(alignment: .leading) {
                    Text(note.title)
                        .foregroundColor(.blue)
                        .font(.headline)
                    Text(note.content)
                        .font(.body)
                        .padding(.vertical)
                
                    HStack {
                        Spacer()
                        Text("\(note.timeStamp)")
                            .foregroundColor(.gray)
                            .italic()
                    }
                }
            }
            .onDelete(perform: deleteNote)
        }
    }
    
    func deleteNote(at offsets: IndexSet) {
        notes.notes.remove(atOffsets: offsets)
    }
}

struct NoteView_Previews: PreviewProvider {
    static var previews: some View {
        NoteView()
            .environmentObject(Notes())
    }
}
AddNew.swift
 
//
//  AddNew.swift
//  SwiftUIProject
//
//  Created by Cairocoders
//

import SwiftUI

struct AddNew: View {
    @State private var title = ""
    @State private var content = ""
    @EnvironmentObject var notes: Notes
    @Environment(\.dismiss) var dismiss
    
    var body: some View {
        Form {
            Section {
                TextField("Give your note a title", text: $title)
                ZStack {
                    TextEditor(text: $content)
                        .frame(height: 200)
                    VStack {
                        Spacer()
                        HStack {
                            Spacer()
                            Text("\(content.count)/120")
                                .foregroundColor(.gray)
                                .padding()
                        }
                    }
                }
                HStack {
                    Spacer()
                    Button("Add note!") {
                        notes.addNote(title: title, content: content)
                        dismiss()
                    }
                    Spacer()
                }
            }
        }
    }
}

struct AddNew_Previews: PreviewProvider {
    static var previews: some View {
        AddNew()
            .environmentObject(Notes())
    }
}

Related Post