Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Are you allowed to save to the managed object context (Core Data) while typing in a TextEditor (Text Field Input)?

The question is best explained in an example:

struct MyEditor: View {
    @Environment(\.managedObjectContext) var managedObjectContext
    
    @ObservedObject var song: Song
    
    var body: some View {
        TextEditor(text: $song.lyrics)
            .navigationTitle(song.title)
            .onChange(of: song.lyrics) { newValue in
                try? managedObjectContext.save()
            }
    }
}

It feels wrong to spam save but I want to make sure the data is stored. Is this allowed and a correct way to do it?

Another way I can think of is to create a publisher that smoothens the signal to save. If this is the correct way to do it. Can I retrieve the publisher from the ObservedObject or do I have to create a different @State property for that and use onChange to pass the values.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

struct MyEditor: View {
    @Environment(\.managedObjectContext) var managedObjectContext
    
    @ObservedObject var song: Song
    
    @State private var lyricsPublisher = PassthroughSubject<String, Never>()
    
    var body: some View {
        TextEditor(text: $song.lyrics)
            .navigationTitle(song.title)
            .onChange(of: song.lyrics) { newValue in
                lyricsPublisher.send(newValue)
            }
            .onReceive(lyricsPublisher
                .debounce(for: 0.5, scheduler: RunLoop.main)
                .removeDuplicates()
            ) { value in
                try? managedObjectContext.save()
            }
    }
}

This is what Song looks like as a ManagedObject.

@objc(Song)
class Song: NSManagedObject, Identifiable {
    @nonobjc class func fetchRequest() -> NSFetchRequest<Song> {
        return NSFetchRequest<Scribble>(entityName: "Song")
    }

    @NSManaged public var id: UUID
    @NSManaged public var title: String
    @NSManaged public var lyrics: String
}

>Solution :

Yes, it is possible to use publisher of managed object (ObservedObject) directly, like

var body: some View {
    TextEditor(text: $song.lyrics)
        .navigationTitle(song.title)
        .onReceive(song.publisher(for: \.lyrics)      // << here !!
            .debounce(for: 0.5, scheduler: DispatchQueue.main)
            .removeDuplicates()
        ) { value in
            try? managedObjectContext.save()
        }
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading