Right now our ContentView
has a query property like this:
@Query var books: [Book]
And we’re using it in body
with this simple text view:
Text("Count: \(books.count)")
To bring this screen to life, we’re going to replace that text view with a List
showing all the books that have been added, along with their rating and author.
We could just use the same star rating view here that we made earlier, but it’s much more fun to try something else. Whereas the RatingView
control can be used in any kind of project, we can make a new EmojiRatingView
that displays a rating specific to this project. All it will do is show one of five different emoji depending on the rating, and it’s a great example of how straightforward view composition is in SwiftUI – it’s so easy to just pull out a small part of your views in this way.
So, make a new SwiftUI view called “EmojiRatingView”, and give it the following code:
struct EmojiRatingView: View {
let rating: Int
var body: some View {
switch rating {
case 1:
Text("1")
case 2:
Text("2")
case 3:
Text("3")
case 4:
Text("4")
default:
Text("5")
}
}
}
#Preview {
EmojiRatingView(rating: 3)
}
Tip: I used numbers in my text because emoji can cause havoc with e-readers, but you should replace those with whatever emoji you think represent the various ratings.
Now we can return to ContentView
and do a first pass of its UI. This will replace the existing text view with a list and a ForEach
over books
. We don’t need to provide an identifier for the ForEach
because all SwiftData models conform to Identifiable
automatically.
Inside the list we’re going to have a NavigationLink
that point to the current book, and inside that we’ll have our new EmojiRatingView
, plus the book’s title and author. So, replace the existing text view with this:
List {
ForEach(books) { book in
NavigationLink(value: book) {
HStack {
EmojiRatingView(rating: book.rating)
.font(.largeTitle)
VStack(alignment: .leading) {
Text(book.title)
.font(.headline)
Text(book.author)
.foregroundStyle(.secondary)
}
}
}
}
}
Tip: Make sure you leave the earlier modifiers in place - navigationTitle()
, etc.
Navigation won't quite work because we haven't added navigationDestination()
just yet, but that's okay – we’ll come back to this screen soon enough. First let’s build the detail view…
SPONSORED Take the pain out of configuring and testing your paywalls. RevenueCat's Paywalls allow you to remotely configure and A/B test your entire paywall UI without any code changes or app updates.
Sponsor Hacking with Swift and reach the world's largest Swift community!
Link copied to your pasteboard.