To wrapup the Bookworm project @twostraws challenges us to add a new date attribute to the Book entity.
Then he says to format that nicely somewhere in DetailView.
Adding a reviewDate to the CoreData model was as simple as adding a new entity, and rebuilding. Then when you create a new book, just assign Date.now to the reviewDate var.
To add business logic to the CoreDate Book class, I created an extension. There I added a few business rules as computed properties. I also created a convenience view to show the review date for Challenge #3.
What I toyed with (examples below) are iOS 15 features for formatting date objects. (Check out Logan's 5 min vid: iOS 15 Date Formatter )
For example:
- reviewDate.formatted(.dateTime.year().day(.twoDigits).month(.abbreviated)) -> Nov 27, 2021 or Jan 03, 2022
- reviewDate.formatted(.dateTime.month(.abbreviated).year())) -> Nov 2021
- reviewDate.formatted(.dateTime.year(.twoDigits).month(.twoDigits)) ) -> 11/21
It's more Swift like to use .abbreviated or .twoDigits rather than the C-like "MMmmmHH-YY" rules.
// Books_Extension.swift
// This extension adds logic to the CoreData class. It's in an extension because CoreData will
// overwrite the Class definition, if you modify the CoreData model.
//
// Created by Obelix on 11/25/21.
import SwiftUI
extension Book {
// isWorstRating is a business rule. This logic should NOT be in the view!
func isWorstRating() -> Bool {
if self.rating == 1 { return true }
return false
}
// Turn the review date into a string for display.
var displayDate : String {
return (reviewDate ?? Date.now) // Core data may not have a value for this
.formatted(.dateTime
.year() // New formatter! 2 or 4 year
.day(.twoDigits) // day has options! 07 or 7
.month(.abbreviated)) // month has more options
// format descriptors are more Swifty. Less C-like.
}
}
// Create a convenience view to use on other forms and views.
struct ReviewDateView: View {
let reviewDate: String
var body: some View {
HStack {
Label ("\(reviewDate)", systemImage: "text.badge.checkmark")
.font(.callout)
.padding([.trailing, .leading])
.background(.indigo)
.clipShape(RoundedRectangle(cornerRadius: 5))
.padding()
Spacer()
}
}
}