Leave a rating/review
Good job on those challenges! You’ve implemented quite a few challenging features so let’s end this part of the course on an easier note. There’s one little thing I’d like to add to the app, and that is to display how many RocketLaunches are associated with each tag.
You could do this by executing a fetch request and counting the results but if you want to do this in several places you need to define fetch requests all over the place which isn’t the best approach - the more you duplicate your logic the more you leave room for error.
Instead you’re going to use Core Data’s transient properties. Navigate to the RocketLaunch data model, select the Tag entity and add a new attribute named launchCount. Set the type to Integer16 and in the data model inspector check the transient box. You’re also going to uncheck the optional box and give it a default value of 0.
You can think of transient properties like computed properties, except they are managed by core data. A transient property is one that is defined in the model, but not saved in the persistent store. Core Data still keeps track of changes to the property in a managed object context but doesn’t save these changes. Transient properties, like computed properties, are useful for computing information based on other properties on the model.
Let’s define one. Start by declaring a property with the @objc keyword.
@objc var launchCount: Int {}
You’re doing this because while this is like a computed property, you want to expose it to the Objective-C runtime so it can be managed by Core Data.
Inside the property declaration you’re going to call a method on NSManagedObject, willAccessValue(forKey:)
willAccessValue(forKey: "launches")
This method takes a key path to an attribute on the same entity and informs Core Data, through key value observing, that the launches property is about to be accessed.
Next you’ll go ahead and access that property and use it to determine a count value
let count = launches.count
After accessing it you’ll tell Core Data that you’re done using it with the didAccessValue(forKey:) method.
didAccessValue(forKey: "launches")
Like its counterpart this tells Core Data that you went ahead and accessed it. Now you can return the value
return count
Let’s use this property in the TagsView to display the number of launches for each tag. Change the Text view inside the ForEach to the following:
Text("\(tag.title) (\(tag.launchCount))")
Build and run the app. If you navigate to the tags view you should see the count for each tag.
So what was the point of this? You could’ve achieved the same functionality with a computed property without the extra method calls. Actually, it’s the extra method calls that make this really useful but to understand that you need to take a slight peek behind the curtains at how Core Data handles things.
One concept I haven’t touched on yet is faulting. When you load the app the first screen you see is a series of launch lists. All of those lists have launches associated with them but they aren’t all fetched immediately when the lists are fetched. If they were that would be extremely inefficient because the app would be holding more data than is necessary in memory.
Have the simulator running to show this
Instead faulting solves this problem by using placeholder objects known as faults. When you’re on the first screen, all of those list objects have a launches property, but at that moment there are no launches fetched and held in memory. Instead Core Data uses a bunch of placeholders. This limits the size of the object graph and saves memory. When you access the launches property on the list object, the fault is realized and Core Data automatically fetches the data associated with that relationship.
So why does this matter, especially in the context of transient properties? Two reasons - by informing Core Data that you are about to access a property Core Data can realize any faults and fetch the data for you.
The second reason is because unlike a computed property, the managed object context actively keeps track of changes to transient properties. This means that even though the data is not stored you get all the benefits of Core Data like undo and redo, validation and so on. Many of these topics are concepts you won’t be covering in this course, but when you do you’ll be able to use them with transient properties as well.
In the next video let’s wrap up this part of the course and recap what you’ve learned.