When Apple launched SwiftData in iOS 17 it was missing the ability to add indexes. Apple corrected that omission in iOS 18.
Core Data Fetch Index
Core Data has long supported adding a fetch index to a property for faster database lookups. For example, if you fetch and sort items by a timestamp you might want to index the timestamp property.
In the Xcode Core Data Model Editor select the entity and then from the Editor
use Add Fetch Index
. Choose a suitable name for the index, change the property field to the name of the property you want to index and decide if you want ascending or descending order:
When Apple shipped SwiftData with Xcode 15 and iOS 17 it did not support database indexes. Apart from the performance impact it was also a concern if you wanted to use your Core Data schema with SwiftData:
In Xcode 15, if you tick the “Used with SwiftData” option in the file inspector Xcode gives you a warning:
Fetch indexes are not supported in SwiftData
That was true in iOS 17 but is no longer true with iOS 18. Unfortunately, Xcode 16 continues to show the same warning. I don’t know if there’s still some incompatibility or if that’s a bug (FB14485495).
Adding SwiftData Fetch Indexes (iOS 18)
First the bad news, this is an iOS 18 feature that does not back deploy to iOS 17. Here’s my SwiftData model for an Item
taken from the Xcode project template:
@Model final class Item {
var name: String
var timestamp: Date
init(name: String, timestamp: Date) {
self.name = name
self.timestamp = timestamp
}
}
Use the #Index
macro to specify the key path for each index you want to add:
@Model final class Item {
// Add indexes for name and timestamp
#Index<Item>([\.name], [\.timestamp])
...
}
You can only use the #Index macro once for each model class so you need to list all the indexes you want in the single macro. Note the subtle difference between adding an index for the individual properties or a compound index (I can see myself getting this wrong):
// Add separate indexes for name and timestamp.
// Also add a compound index for name and timestamp.
#Index<Item>([\.name], [\.timestamp], [\.name, \.timestamp])
The compound index would be useful if my items had duplicate names that I wanted to sort in timestamp order.