BLACK FRIDAY SALE: Save big on all my Swift books and bundles! >>

Note Taking App Display Issue

Forums > SwiftUI

Hello!

I am creating my first Swift UI app which is really simple but there is one thing I can't figure out. I have two views: a main view which display a list of notes and a view of a note.

I have two problems with my project, one is a cosmetic one and the other is prettty crucial.

  1. A note title is define by the note content - when you type in the TextFielw the title is automatically updated. The problem is after you type in a first symbol the field gets inactive. You have to click in the TextField again to continue typing.
  2. Content of notes is not saved. I cant create a note, go into it and type something, but when I go back to the main view and click on the note I have jsut updated, it is empty.

I would really appreciate if you could review and let me know my mistakes. Here's the repository - https://github.com/AleksLip/NoteApp

Thank you in advance!

   

Aleks seeks help with ObservableObjects, etc.

Content of notes is not saved. I can create a note, go into it and type something,
but when I go back to the main view and click on the note I have just updated, it is empty.

In this code snip below, you define allMyNotes as a collection of Note objects.

Also you're telling SwiftUI to let views know when the array named allMyNotes changes. That is, when you ADD a new note, DELETE a note, or REORDER the array.

I am not sure this object publishes notifications when you change the VALUES inside a single Note object. How might you test this?

class ListViewModel: ObservableObject {
    // Are you confusing yourself?  
    // myNote is not ONE note, it's a collection of ALL your notes.
    // Rename this to allMyNotes, or something similar
    // Also, consider renaming your object to Note, rather than Notes. It's just ONE note.

    // Your code:
    // @Published var myNote: [Notes] = [] {  // <-- confusing??

    // Instead consider:
    @Published var allMyNotes: [Note] = []  // <-- Less confusing? allMyNotes is a collection of Note objects.
        // Any time allMyNotes changes, the code below runs
        didSet { saveAllMyNotes() }
    }

1      

Also, you may want to review this thread. I think it answers the same question you're asking.

See -> Array of Observable Objects

And this article from Sundell.

See -> Taking Notes!

1      

Hi @Obelix!

Thank you for your notes, it does make sense to change the name of the struct and variable in the class, it makes more sense.

I have read the article you shared and it prompted me to think that my notes are not saved because I do not trigger the updateNotes function. First, I added a button and it did the trick:

Button("Save") {
  listViewModel.updateNotes(item: noteItem)
}

Then I googled how to automatically save whenever there is a change in the view, and I changed it to this (ut went under "Form"):

.onChange(of: noteItem.noteText) { item in
  listViewModel.updateNotes(item: noteItem)
}

Now when I navigate to any note I have just type somthing in, I can see the changes. But I still had the problem with the main view which had the list of the notes. The notes' title was still default unlike the title in the NoteView which would dynamically change based on the TextField value.

I failed to figure out why until I realized I put the variable in the ForEach which would return a default value of "title". I changed it to "noteText" and the title became dynamic:

ForEach(listViewModel.allMyNotes) { index in
                    NavigationLink(index.noteText) {
                        NoteView(noteItem: index)
                    }
                }

It is not what I need though, I would like each noteItem to update its "title" which my code can't do at the moment. I do think it has to be in the header section of the NoteView but I don't what exavtly to put there.

//
//  NoteView.swift
//  ToDo
//
//  Created by Aleksandr Lipatov on 09.09.2022.
//

import SwiftUI

struct NoteView: View {

    @EnvironmentObject var listViewModel: ListViewModel
    @State var noteItem: Note

    var body: some View {

        Form {
            Section {
                TextField("Note", text: $noteItem.noteText)
                    .padding()
                    .clipped()

            } header: {
                if (noteItem.noteText.count >= 1) {
                    Text(noteItem.noteText)
                }
                else {
                    Text(noteItem.title)
                }
            }
        }
        .onChange(of: noteItem.noteText) { item in
            listViewModel.updateNotes(item: noteItem)
        }
    }
}

struct NoteView_Previews: PreviewProvider {
    static var noteItem1 = Note(title: "Text", noteText: "Text")
    static var previews: some View {
        NavigationView {
            NoteView(noteItem: noteItem1)
        }
        .environmentObject(ListViewModel())
    }
}

And I still have this problem:

A note title is define by the note content - when you type in the TextFielw the title is automatically updated. The problem is after you type in a first symbol the field gets inactive. You have to click in the TextField again to continue typing.

   

Hacking with Swift is sponsored by RevenueCat

SPONSORED In-app subscriptions are a pain to implement, hard to test, and full of edge cases. RevenueCat makes it straightforward and reliable so you can get back to building your app. Oh, and it's free if your app makes less than $10k/mo.

Learn more

Sponsor Hacking with Swift and reach the world's largest Swift community!

Reply to this topic…

You need to create an account or log in to reply.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.