NEW: My new book Pro SwiftUI is out now – level up your SwiftUI skills today! >>

Building a list with @FetchRequest

Paul Hudson    @twostraws   

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:
        case 2:
        case 3:
        case 4:

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)

                VStack(alignment: .leading) {
                    Text(book.title ?? "Unknown Title")
                    Text( ?? "Unknown Author")

We’ll come back to this screen soon enough, but first let’s build the detail view…

Hacking with Swift is sponsored by Essential Developer

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.

Click to save your free spot now

Sponsor Hacking with Swift and reach the world's largest Swift community!

Buy Pro Swift Buy Pro SwiftUI Buy Swift Design Patterns Buy Testing Swift Buy Hacking with iOS Buy Swift Coding Challenges Buy Swift on Sundays Volume One Buy Server-Side Swift Buy Advanced iOS Volume One Buy Advanced iOS Volume Two Buy Advanced iOS Volume Three Buy Hacking with watchOS Buy Hacking with tvOS Buy Hacking with macOS Buy Dive Into SpriteKit Buy Swift in Sixty Seconds Buy Objective-C for Swift Developers Buy Beyond Code

Was this page useful? Let us know!

Average rating: 4.8/5

Unknown user

You are not logged in

Log in or create account

Link copied to your pasteboard.