This is a follow-up to my follow-up, with many thank yous to @jakcharvat for all their help so far. It might be a little long, apologies in advance, but I may need to get into a bit of the nitty-gritty with my views and data model.
I've got a pretty straight-forward side-by-side list and detail view set up. The list view presents options for sorting and filtering a library of books, series, authors, etc. (All credit for David Weber for creating a series convoluted enough that I decided I needed to learn Swift in order to create a library management app capable of dealing not just with series, but series within series. No copyright infringement intended with the following screenshots.)
As you can see here, I've got two "refinement" options for the list on the side:
"Sort" is simply the list of books, sectioned in various ways (by author, by series, and so forth.) That button to the upper right of the cover image in the detail view is a cycling button that allows the user to set the book's status to four different states: unread, in progress, completed, and favorite.
Last week, when I was working on that portion of things, I had trouble getting the list to update when that button was used to change the book's status. If you were browsing books with a status of "To Be Read" and changed the selected book's status to "Completed", it wouldn't be removed from the "To Be Read" list until the list view was changed by chosing another sorting option and then returning to "To Be Read".
To solve that, I added an
That worked, so as you can see, now when the
Now I'm trying to do the same with my filtering views, particularly with my rating view without much success.
The filtering list view is a bit more complicated, because of the user-interactive elements. I don't yet have any code in place to handle situations where the user edits book metadata (like title or language), so I can't say what would happen to the filtering view if the user made those edits. That will come later. For now, the only two parts of the book record that are editable from the detail view are
And as you can see, when changing the rating, the list view does not update:
If you change the list view (by selecting a different filtering criteria), you can see the book record has had its "rating" property changed as it should, and that it shows up when filtering by that rating:
And when you return to the previous filtering criteria, the book is no longer in the list:
But that change isn't happening in real-time in the current view, the way it does with
The results are the same regardless of whether or not I include the
I've also tried creating an
But that made things even worse, because the list in the listview wouldn't populate at all, or the very first listview displayed would be populated, but if you changed to another filtering criteria, the list view would be empty (including the first list view that was displayed, upon returning to it.)
I've pretty much exhausted my bag of tricks at this point and have no idea what to try next.
Edit: Hmm. Screenshots didn't come through. Here is a link if interested.
Hello once again, and thanks for the shoutout 😊
This time I haven't used a lot of your code, but created a proof of concept that should have the behaviour you're after. Working with Bindings inside List (and for that matter also ForEach) views is a pain in SwiftUI, and every time I have face it (and it's quite often) I seem to come up with a different solution. At the bottom of the post is a full example that you can paste into Xcode and play around with, but let me start off by walking you through the important bits one by one.
The enum I use for my rating selection. You're using plain doubles and that should work as well, I wanted to incorporate a "not filtering" state into my rating picker as well so that's why I use this. The
My book. Very simple, no
Just a convenience property with sample books. Generates 5 books of each rating (0...5) and names them by their initial rating and idx within that rating.
App Data Object
This is an important bit. This has all the data for the app. It keeps track of all the books, even when filtering, and the currently selected rating filter. The
Those are the two views. Few things to note here. Standard picker, just segmented because I think it fits better in the sidebar. The
The rest is pretty simple: in the
Thank you again. I will work with it and see what I can do as far as modifying it to fit with my data model and the fact that filtering can also be applied to my library's
I also wanted an "unrated" options in the ratings datasource, but hadn't thought to make it an enum with associated values to accomplish that.
I've suspected since the beginning that my approach to having the whole database floating around as an
Thank you. I will let you know if I have any questions.
You're welcome :) I wrote the sample with your code in mind, so hopefully it should work without issues.
That enum idea for ratings struck me when I wanted to implement it by also allowing
As for the data management, that's still a big question regarding SwiftUI. I myself battle with it in every project, where do I put this stuff, how can I bind this together etc. I always tend to fall to just attaching it to my environment at the topmost view, usually right inside my
Do let me know if it doesn't work, or if I can help you with anything else, I'm happy to do so :)
I've wrote and discard two extremely code-heavy replies tonight, because in the greater context of trying to present a view where there are multiple filtering and sorting options, I haven't really been able to implement an approach where I can just refer to a particular book by its index in the whole array of books in the database. Because sometimes the array I'm dealing with isn't the whole array of books in the database. Sometimes it's the array of books written by an author, or the books in a series (which is an array of tuples,
But every time I try to get into what issue I'm having, I end up putting in so much code, trying to explain what I'm doing, and what I've tried, that I figure the message is unreadable and I delete it and go back to trying to muddle through on my own, and getting nowhere doing it.
So. Let's start at the very top and work our way down, view by view.
This is the way I've had it set up since before your last reply to me, @jakcharvat, but it's reassuring to know that this approach isn't entirely wrong.
At the top, I have this:
So, focusing on just this part for now, to make sure I understand the most fundamental concepts, let me ask this:
The documentation says that an
If I make a change to the
If the answer to that question is supposed to be "yes", then I'm clearly doing something wrong from the get-go, because that isn't happening.
(More questions to come once I know whether or not my understanding of that portion of things is accurate.)
With some help from my mentor, I've managed to solve this problem with methods querying everything from my
So the result looks like this and behaves the way it's supposed to:
SPONSORED Superwall lets you build & test paywalls without shipping updates. Run experiments, offer sales, segment users, update locked features and more at the click of button. Best part? It's FREE for up to 250 conversions / mo and the Superwall team builds out 100% custom paywalls – free of charge.
This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.
All interactions here are governed by our code of conduct.
Link copied to your pasteboard.