This is, in part, a follow-up to my question last week.
I have an enum of options for filtering in my library management app:
enum Filtering: String, CaseIterable {
case none = "Reset"
case title = "Title"
case author = "Author"
case series = "Series"
case collection = "Collection"
case genre = "Genre"
case keyword = "Keyword"
case rating = "Rating"
case language = "Language"
All but the last two options are fairly straightforward text-filtering for which I adapted this HWS+ tutorial.
The last two require picker views, however. But I'm running into a strange problem when I attempt to work those picker views into a view that encompasses all the optios:
This works as intended:
var ratings = [0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0]
@State private var starRatingSelection: Double = 0.0
var body: some View {
return NavigationView {
VStack {
Picker(selection: $starRatingSelection,
label: Text("Search by rating"),
content: {
ForEach(ratings, id: \.self) { rating in
viewForRating(rating)
}
})
List(library.database.books.filtered(starRating: starRatingSelection)) { book in
let bookObject = AudiobookObject(book)
BookRowView(audiobook: bookObject)
}
.listStyle(InsetListStyle())
}
.navigationBarTitle("Rating")
}
}
This, however, does not:
var ratings = [0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0]
@State private var starRatingSelection: Double = 0.0
@State private var filteredBooks = [Audiobook]()
var body: some View {
switch filtering {
case .title: byTitleView
case .author: byAuthorView
case .series: bySeriesView
case .collection: byCollectionView
case .genre: byGenreView
case .rating: starRatingPickerView
case .language: languagePickerView
case .keyword: byKeywordView
default: LibraryView()
}
}
private func applyFilter() {
switch filtering {
case .title: filteredBooks = library.database.books.sorted(by: filterString)
case .author: filteredAuthors = library.database.authors.filtered(by: filterString)
case .series: filteredSeries = library.database.series.sorted(by: filterString)
case .collection: filteredCollections = library.database.collections.sorted(by: filterString)
case .genre: filteredGenres = library.database.genres.sorted(by: filterString)
case .rating: filteredBooks = library.database.books.filtered(starRating: starRatingSelection)
case .language: filteredBooks = library.database.books.booksByLanguage(languageSelection)
case .keyword:
filteredBooks = library.database.books.booksByKeyword(filterString)
filteredSeries = library.database.series.filtered(by: filterString)
filteredCollections = library.database.collections.filtered(by: filterString)
default: filteredBooks = library.database.books.sorted(by: "")
}
}
private var starRatingPickerView: some View {
return NavigationView {
VStack {
Picker(selection: $starRatingSelection,
label: Text("Search by rating"),
content: {
ForEach(ratings, id: \.self) { rating in
viewForRating(rating)
}
})
List(filteredBooks) { book in
let bookObject = AudiobookObject(book)
BookRowView(audiobook: bookObject)
}
.onAppear(perform: applyFilter)
.listStyle(InsetListStyle())
}
.navigationBarTitle("Rating")
}
}
Which... doesn't make sense to me. The only difference between the two (at least so far as the picker portion is concerned) is that instead of:
List(library.database.books.filtered(starRating: starRatingSelection)) { book in
let bookObject = AudiobookObject(book)
BookRowView(audiobook: bookObject)
}
I'm using:
List(filteredBooks) { book in
let bookObject = AudiobookObject(book)
BookRowView(audiobook: bookObject)
}
I can get around it by bypassing applyFilter()
and just making that one change, and it works:
private func applyFilter() {
switch filtering {
case .title: filteredBooks = library.database.books.sorted(by: filterString)
case .author: filteredAuthors = library.database.authors.filtered(by: filterString)
case .series: filteredSeries = library.database.series.sorted(by: filterString)
case .collection: filteredCollections = library.database.collections.sorted(by: filterString)
case .genre: filteredGenres = library.database.genres.sorted(by: filterString)
case .keyword:
filteredBooks = library.database.books.booksByKeyword(filterString)
filteredSeries = library.database.series.filtered(by: filterString)
filteredCollections = library.database.collections.filtered(by: filterString)
default: filteredBooks = library.database.books.sorted(by: "")
}
}
private var starRatingPickerView: some View {
return NavigationView {
VStack {
Picker(selection: $starRatingSelection,
label: Text("Search by rating"),
content: {
ForEach(ratings, id: \.self) { rating in
viewForRating(rating)
}
})
List(library.database.books.filtered(starRating: starRatingSelection)) { book in
let bookObject = AudiobookObject(book)
BookRowView(audiobook: bookObject)
}
.listStyle(InsetListStyle())
}
.navigationBarTitle("Rating")
}
}
But I'd much rather understand WHY it isn't working, rather than just getting around it with guesswork.