TEAM LICENSES: Save money and learn new skills through a Hacking with Swift+ team license >>

Editable list view inside an editable list view?

Forums > SwiftUI

I'm on day 42 of Hacking with Swift so I'm only familiar with the basics of Codable and ObservableObject.

That said, I had this brilliant idea for a simple enough app the other day that would comprise an editable list view of courses I'm taking in school, where each list item or course would be a navigation link that would take you into an editable list view of all the assignments you have in that class. A homework tracker, essentially.

But I've tried everything, and I cannot, for the life of me, get an editable list view inside of an editable list view, and have them all save to UserDefaults.

The way my code works right now, I have:

a class Courses: ObservableObject, Codable with a single Published property, items: [Course] that saves to UserDefaults when it's didSet observer is called. Also has a custom initializer that loads everything from UserDefaults properly.

a struct Course: Identifiable, Codable with a bunch of constant properties (and it's ID) and an instance of the class Assignments

a class Assignments: ObservableObject, Codable with a single Published property, items: [Assignment] that saves to UserDefaults when it's didSet observer is called. Also has a custom initializer that loads everything from UserDefaults properly.

and a struct Assignment: Identifiable, Codable with just constant properties (and it's ID)

I have a ContentView that observes Courses and lets the user edit the items: [Course] list, and a CourseView that takes a course and observes Assignments and lets the user edit the items: [Assignment] list.

But Courses doesn't detect when any Assignments instances are updated, making it so that ContentView doesn't update and none of the assignments are loaded OR saved when the app starts or stops. I know I have to somehow get Courses to recognize that it's been changed whenever an Assignments instance has been changed, but I have no idea how to send that up the chain. I tried passing down a reference to my Courses instance but just ended up creating an infinitely recursive loop when encoding and decoding since Courses has a property items has instances Course has a property Courses has a property items etc.

I'm not sure if this is even the right data configuration, if these should be structs or classes or whatever. But I've looked everywhere online and even asked ChatGPT several, several times, and not even it has come up with a good answer.

TL: DR; How in the world can you come up with an editable list view where every row is a NavigationLink that leads to it's own editable list view, and where all the rows and all the data saves and loads upon re-entering the app?

2      

Delete the class Assignments but keep the struct Assignment.

In the class Courses, the assignments property should not be of type Assignments. Instead, it should be of type [Assignment], i.e., an array of Assignment items.

2      

Now the problem is that, since my Course object is immutable inside it's respective CourseView, I can't add or delete assignments. Making it a state variable doesn't work either; I tested it and it runs, but it doesn't even add assignments in the first place anymore.

2      

Firstly, your data structure seems reasonable, but you need to establish proper relationships between your data models to ensure changes in assignments reflect on courses and vice versa. You mentioned that you tried passing references, which caused recursion issues. Instead, you can set up relationships in a one-to-many fashion using identifiers. Here's an approach:

Data Models:

Course: ObservableObject, Codable, Identifiable

Properties: id, name, assignments (array of assignment IDs) Assignment: ObservableObject, Codable, Identifiable

Properties: id, name, dueDate, etc. ViewModels:

CoursesViewModel: ObservableObject

Property: courses (an array of Course objects) Methods: Add, update, and delete courses AssignmentsViewModel: ObservableObject

Property: assignments (an array of Assignment objects) Methods: Add, update, and delete assignments Relationships:

In your ViewModel, when you add or update an assignment for a course, make sure to update the assignments array of that course and vice versa. UserDefaults:

When updating the data in your ViewModel, also update UserDefaults to save the changes. You can use UserDefaults suites to separate your data, so you don't need to worry about conflicts. View Hierarchy:

ContentView observes CoursesViewModel and displays a list of courses. CourseView observes a selected course from CoursesViewModel and displays assignments for that course. Binding and Navigation:

When navigating to the CourseView, pass the selected course as a binding to ensure it can update assignments. Use NavigationLinks or a custom navigation stack to handle the navigation. Data Loading:

In your @App's onAppear, load your data from UserDefaults and initialize your ViewModel with the loaded data. Data Synchronization:

Ensure that when you update assignments or courses, your ViewModel sends out objectWillChange events to notify the SwiftUI views to refresh. Error Handling:

Handle errors gracefully, especially when working with UserDefaults. By following this approach, you can create an editable list view where each row is a NavigationLink leading to its own editable list view, and all data is properly synchronized and saved in UserDefaults. Remember to handle edge cases like data initialization, deletion, and error handling. This architecture should help you achieve your desired functionality without causing infinite loops or data synchronization issues.

2      

Hacking with Swift is sponsored by String Catalog.

SPONSORED Get accurate app localizations in minutes using AI. Choose your languages & receive translations for 40+ markets!

Localize My App

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.