Right now our ContentView
has a fetch request property like this:
@FetchRequest(sortDescriptors: []) var books: FetchedResults<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: Int16
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")
}
}
}
struct EmojiRatingView_Previews: PreviewProvider {
static var previews: some View {
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.
Notice how that specifically uses Int16
, which makes interfacing with Core Data easier. And that’s the entire view done – it really is that simple.
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 Core Data’s managed object class conform to Identifiable
automatically, but things are trickier when it comes to creating views inside the ForEach
.
You see, all the properties of our Core Data entity are optional, which means we need to make heavy use of nil coalescing in order to make our code work. We’ll look at an alternative to this soon, but for now we’ll just be scattering ??
around.
Inside the list we’re going to have a NavigationLink
that will eventually point to a detail view, 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 {
Text(book.title ?? "Unknown Title")
} label: {
HStack {
EmojiRatingView(rating: book.rating)
.font(.largeTitle)
VStack(alignment: .leading) {
Text(book.title ?? "Unknown Title")
.font(.headline)
Text(book.author ?? "Unknown Author")
.foregroundColor(.secondary)
}
}
}
}
}
We’ll come back to this screen soon enough, but first let’s build the detail view…
SPONSORED Join a FREE crash course for mid/senior iOS devs who want to achieve an expert level of technical and practical skills – it’s the fast track to being a complete senior developer! Hurry up because it'll be available only until October 1st.
Sponsor Hacking with Swift and reach the world's largest Swift community!
Link copied to your pasteboard.