Fetched properties are a feature of Core Data, similar in concept to computed properties on Swift objects. This post presents an overview of fetched properties in Core Data with an example, and provides an alternative implementation:

  1. Core Data Fetched Properties
  2. Fetched Property Example
  3. Alternative To Core Data Fetched Properties

Core Data Fetched Properties

Fetched Properties in Core Data are properties that return an array value from a predicate. A fetched property predicate is a Core Data query that evaluates to an array of results. In this blog post, a fetched property called contractors will be created on a Business entity that will return an array of all People in the Business that are contractors.

Fetched Property Example

First, create a Core Data model with two entities: Person and Business. Person has name and type String attributes. Business has a name String attribute. Business also has a one-to-many relationship people to Person, the inverse is the job relationship on Person. Adding the Person and Business entities to a Core Data model should look like this:

Core Data Business Entity
Core Data Business Entity
Core Data Person Entity
Core Data Person Entity

Next, add a fetched property contractors to Business. This can be done by clicking the + button under the Fetched Properties section in Business entity. Name the fetched property contractors and enter the following query for the predicate:

type LIKE [c] "contractor" AND job == $FETCH_SOURCE

You may be wondering what LIKE [c] and $FETCH_SOURCE mean. This post presents an example of Fetched Properties for reference, but there are other implementations to consider that do not use complex query language. Please make sure to read the Alternative To Core Data Fetched Properties section below! If you determine fetched properties are the right approach for you, the Apple Core Data Documentation on Weak Relationships (Fetched Properties) goes into detail about predicate syntax specific to fetched properties.

Adding the contractors fetched property on the Business entity will look like:

Core Data Fetched Property Predicate
Core Data Fetched Property Predicate

Next, click on the contractors Fetched Property and set the Destination to Person in the Attributes Inspector. The Destination is the entity type a fetched property will query using the Predicate:

Core Data Fetched Property Destination

Now, the fetched property can be used in Swift:

// Get Core Data managed object context
let delegate = UIApplication.shared.delegate as! AppDelegate
let context = delegate.persistentContainer.viewContext

// Create People core data models
let steve = Person(context: context)
steve.name = "Steve"
steve.type = "contractor"

let tim = Person(context: context)
tim.name = "Tim"
tim.type = "employee"

let amelia = Person(context: context)
amelia.name = "Amelia"
amelia.type = "contractor"

// Create a Business core data model
let business = Business(context: context)
business.name = "Orange Computers"

business.addToPeople(tim)
business.addToPeople(steve)
business.addToPeople(amelia)

// Save context
try! context.save()

// Use fetched property
let contractors = business.value(forKey: "contractors")
    as! [Person]

for person in contractors {
    print(person.name)
}

// Expected output:
// Steve
// Amelia

Alternative To Core Data Fetched Properties

A Core Data fetched property has some drawbacks that developers should be aware of:

  1. Debugging fetched properties is more difficult than debugging Swift code, and in some cases no errors are logged even if a fetched property resulted in an error
  2. Fetched properties cannot take arguments the same way as Swift functions can
  3. Fetched properties are cached when evaluated, meaning fetched properties may not always return the expected value without refreshing the object.

Implementing a computed property in a Swift Core Data model extension is often a clear, more intuitive way to implement a fetched property. Here is an alternative example implementation that produces the same result as the fetched property example without the drawbacks:

// Extend the Business entity
extension Business {
    // Create a contractors computed property
    var contractors: [Person] {
        // Use a predicate to filter the people relationship
        let predicate = NSPredicate(
            format: "type LIKE [c] %@", "contractor"
        )

        return Array(people!.filtered(using: predicate))
            as! [Person]
    }
}

Fetched Properties In Core Data

That’s it! In some cases core data fetched properties may provide a useful way to execute predicates, but there is often a better implementation without the drawbacks associated with fetched properties in Swift.