Set Up Core Spotlight with Core Data: Getting Started
Learn how to connect Core Data with Core Spotlight and add search capability to your app using Spotlight. By Warren Burton.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Set Up Core Spotlight with Core Data: Getting Started
30 mins
- Getting Started
- Adding Spotlight to Your Core Data Model
- Configuring Spotlight in Your Persistent Store
- Creating a Spotlight Delegate
- Connecting a Spotlight Delegate
- Describing Searchable Items
- Trying It Out
- Heavy Lifting
- Building a Bridge
- Importing From an API
- Running the Fetch
- Opening a Search Result in Your App
- Including Image Thumbnails with Spotlight
- Deleting Spotlight Data
- Searching Inside the App
- Searching Core Spotlight
- Searchable SwiftUI
- Where to Go From Here?
Many apps you build are containers for your customers’ information, and it’s up to you to provide great ways to let your customer search for that information. However, if the only way to find that information is to open your app and search for it, it makes it difficult for your users. You could instead expose that information to Spotlight and have your app results appear there.
When you have a lot of information that has a complex structure, Core Data is the preferred way of storing your app data. It’s super fast, and as long as you follow a few simple rules, it’s easy to use. The framework has been around for more than 15 years, and Apple engineers have been improving it this whole time.
In this tutorial, you’ll learn how to:
- Upgrade your Core Data model to support Core Spotlight.
- Create a custom
NSCoreDataCoreSpotlightDelegate
to connect your database toCoreSpotlight
. - Start and stop the indexer when needed.
- Use
CoreSpotlight
for searching within your app.
Getting Started
Download the starter project by clicking the Download Materials button at the top or bottom of the tutorial.
You’ll be using a bug tracking utility app, PointyBug. If you’ve already read Drag and Drop Tutorial for SwiftUI, you’ll be familiar with this app.
The persistent storage of PointyBug uses Core Data, and you’ll be adding extra code to expose your data to Spotlight.
Open the Xcode project in the starter directory. First, ensure that the simulator is set to iPad Pro (11-inch) (3rd generation):
Then, build and run. Rotate the simulator to landscape mode to see both the bug list and the details:
Tap ADD BUG, then tap the image picker button at top right of the detail view to add an image. Nothing happens when you tap the button, which seems like a bug. Fortunately, you can use drag and drop to import an image. Trigger a screenshot from the simulator by using the menu Device ▸ Trigger Screenshot.
The screenshot will appear at the bottom-left corner of the screen. Drag and drop that small image to the detail view:
Drag the arrow image at the bottom to add a pointer to show where the problem is. Next, add a description of Image picker button in navigation bar doesn’t show image picker. Then, press Return. Finally, set the status to Open by tapping the gray “No Tag” icon. Now, you have your first bug report:
Press Command-Shift-H to return to the Home Screen and trigger a save.
What you have is a shoe box app: a place to put bits of useful information. But without a system search, it has limited long-term value for your users. Your next task is to add the code to expose your data to the system.
Adding Spotlight to Your Core Data Model
Your first task is to change your Core Data model to let Spotlight know what parts of your model to index.
In the Project navigator, locate the group PointyBug ▸ Model ▸ Core Data. Select PointyBug.xcdatamodeld:
Select CDBug and then text. In the Data Model inspector, check the box for Index in Spotlight:
You took the first step of connecting your data to Spotlight. The next step is to configure NSPersistentContainer
to allow indexing.
Configuring Spotlight in Your Persistent Store
In Core Data, open CoreDataStack.swift. This class wraps all the code needed to create an NSPersistentContainer
that has all the machinery to work with a Core Data store.
Find makeStore(at:)
. This method creates an NSPersistentStoreDescription
that describes how you want your store to work. Next, locate this line:
storeDescription.type = NSSQLiteStoreType
Below it, add the following:
storeDescription.setOption( true as NSNumber, forKey: NSPersistentHistoryTrackingKey)
This tells the store to use persistent history tracking. Setting this option is necessary for a Spotlight indexed store. The store will now record the changes you make and use those change sets to work out what to index.
In the same file, find isPreviewContext
. This switch tells the persistent store to be memory resident when used in SwiftUI previews. Using NSInMemoryStoreType
means there’s no file mess to clean up. For the same reason, this is also a useful configuration when doing unit testing.
Your next task is to create an instance of NSCoreDataCoreSpotlightDelegate
for the NSPersistentStoreCoordinator
.
Creating a Spotlight Delegate
NSCoreDataCoreSpotlightDelegate
describes a set of methods that enable integration of a Core Data store with Core Spotlight:
In the Project navigator, select Core Data and create a new Swift file named BugSpotlightDelegate.swift. Add the following code to the file:
import CoreData import CoreSpotlight class BugSpotlightDelegate: NSCoreDataCoreSpotlightDelegate { override func domainIdentifier() -> String { return "com.raywenderlich.pointybug.bugs" } override func indexName() -> String? { return "bugs-index" } }
BugSpotlightDelegate
is a subclass of NSCoreDataCoreSpotlightDelegate
. In this subclass, you override a couple of attributes to define some names that establish a connection between your app and Core Spotlight. domainIdentifier
should be a reverse-coded domain that builds on your app’s bundle identifier, com.raywenderlich.pointybug.
That’s all you need for a start. Next, you’ll plug BugSpotlightDelegate
into your store.
Connecting a Spotlight Delegate
You created NSCoreDataCoreSpotlightDelegate
, so now you can attach it to your store. Open CoreDataStack.swift.
Add this property to the top of CoreDataStack
:
private(set) var spotlightIndexer: BugSpotlightDelegate?
Then, add this extension to the end of the file:
extension CoreDataStack { func toggleSpotlightIndexing(enabled: Bool) { guard let spotlightIndexer = spotlightIndexer else { return } if enabled { spotlightIndexer.startSpotlightIndexing() } else { spotlightIndexer.stopSpotlightIndexing() } } }
This is a helper to keep start and stop logic for NSCoreDataCoreSpotlightDelegate
in one place.
Now, locate configureContainer()
. Inside the trailing closure of container.loadPersistentStores
, add the code below at the marker // insert here
:
if !self.isPreviewContext { let coordinator = self.container.persistentStoreCoordinator self.spotlightIndexer = BugSpotlightDelegate( forStoreWith: storeDescription, coordinator: coordinator) self.toggleSpotlightIndexing(enabled: true) }
In this fragment, you create BugSpotlightDelegate
with information about your store. Then, you tell Core Spotlight to start doing its work.
There’s one last step: You need to provide a package of information that describes a searchable item.