A search query object manages the criteria to apply when searching app content that you have previously indexed by using the Core Spotlight APIs.


To search app content that you’ve indexed, create a CSSearchQuery object by specifying a formatted query string and an array of attribute names that correspond to properties defined by CSSearchableItemAttributeSet (to learn more about indexing items in your app, see Index App Content). After you start the query, you receive batches of matching CSSearchableItem objects in the handler you implement for the foundItemsHandler property. When the query has returned all the items it found, it calls your completion handler and passes nil to indicate that it completed successfully.

Creating a Query String

Query strings operate on the values associated with a property in a CSSearchableItemAttributeSet object. A query string can take either of the following forms:

  • attributeName operator value[modifiers]

  • InRange(attributeName, minValue, maxValue)

In both forms, attributeName represents the name of a property. The attributeName operator form is well suited to a wide range of matches, especially when you take advantage of operator to combine predicates (possible operators are listed in Table 1) and modifiers to specify types of comparisons to perform on a property’s value (possible modifiers are listed in Table 2). In addition to specifying modifiers, you can also use the * character as a wild card that lets you match substrings in various locations within a string. Use the InRange form to match numeric values associated with the attributeName property that are within the range specified by minValue and maxValue.

For example, consider an app that uses the code shown below to index searchable items with titles that start with the string "Searchable":

let attributes = CSSearchableItemAttributeSet(itemContentType: kUTTypeItem as String)
attributes.title = "Searchable Item #1"

To match all searchable items that have titles that begin with “Searchable,” this app can create the following query string, which uses the = operator and the * wild card character.

title == "Searchable*"

Working with Operators, Modifiers, and the Wild Card

Operators let you specify the relationship between a value and a property, such as equal or not equal. Modifiers let you specify types of text-based comparisons, such as case insensitive or word-based.

You can create a query string using the operators listed in Table 1.

Table 1

Query string operators






Not equal


Less than (used only for numeric and date values)


Greater than (used only for numeric and date values)


Less than or equal (used only for numeric and date values)


Greater than or equal (used only for numeric and date values)

To specify one or more types of text-based comparison, you can use the modifiers listed in Table 2.

Table 2

Comparison modifiers

Use this modifier...

To specify a comparison that is...


Case insensitive.


Insensitive to diacritical marks.


Word-based. In addition, the comparison detects transitions from lower-case to upper-case.


Performed on the tokenized value. For example, values passed directly from a search field are tokenized.

Table 3 lists some examples of modifier usage.

Table 3

Modifier examples

Query string

Example matches

title == “Paris”

“Paris”, but not “paris” or “I love Paris”.

title == “Paris”c

“Paris” and “paris”, but not “I love Paris”.

title == “Paris”wc

“Paris”, “paris”, “I love Paris”, and “paris- france.jpg”, but not “Comparison”.

title == ‘Window’w

“MyWindowClass” and “Broken Window”, but not “NSWindow”.

authorNames == "Frédéric"

“Frédéric”, but not “Frederic”.

authorNames == "Frédéric"cd

“Frédéric” and “Frederic”, regardless of the word case.

Although you can use the wild card character (*) to match a substring at the beginning, end, or interior of a string, it’s often a better idea to use the w modifier to do smart word matching instead. Table 4 lists some examples of using the wild card in a query string.

Table 4

Wild card examples

Query string

Example matches

title == “paris*”

Values that begin with “paris”, such as “paris” and “parisol”, but not “comparison”.

title == “*paris”

Values that end with “paris”.

title == “paris”

Values that contain "paris" anywhere within the string, such as “paris”, “parisol”, and “Comparison”.

title == ‘paris’

Values that are exactly equal to “paris”.

Combining Queries

You can combine queries by using a C-like syntax for AND (&&) and OR (||). For example, you might create the following query to match audio items that were authored by Steve:

authorNames == "Steve"wc && contentType == "audio"wc

You can also use parentheses to group query matching. For example, to match audio or video items that were authored by either Steve or Kevin, you can create the following query string:

(authorNames == "Kevin"wc || authorNames == "Steve"wc) && (contentType
 == "audio"wc || contentType == "video"wc)

Matching Dates and Times

You can create queries that use date and time as the search value. Date and time values are formatted as floating-point values that are compatible with CFDate, and represent seconds relative to January 1, 2001.

In addition, you can use $time values to specify values relative to the current time. For example, to restrict a search to match only the searchable items that completed in the last 10 days, you might use the following query:

(authorNames == "Kevin"wc || authorNames == "Steve"wc) &&

Table 5 lists the properties of $time that you can use to specify dates and time periods relative to the current time.

Table 5

Properties of $time

$time property



The current date and time


The current date


Yesterday’s date


The week preceding the current week


The current week


The current month


The current year


The date and time that results when NUMBER, a positive or negative value that represents seconds, is added to the current time


The date that results when NUMBER, a positive or negative value that represents days, is added to the current day


The date that results when NUMBER, a positive or negative value that represents weeks, is added to the current week


The date that results when NUMBER, a positive or negative value that represents months, is added to the current month


The date that results when NUMBER, a positive or negative value that represents years, is added to the current year


The date represented by parsing the specified ISO-8601-STR compliant string

Putting It All Together

Here is an example of using CSSearchQuery in your app:

import CoreSpotlight
 class QueryExample {
     var query : CSSearchQuery? = nil
     func startQuery(withTitle title : String) {
         var allItems = [CSSearchableItem]()
          // All the items that start with the specified title property using case insensitive comparison
         let queryString = "title == '\(title)*’c"
         let attributes = ["title", "displayName", "keywords",
         self.query = CSSearchQuery(queryString : queryString,
 attributes : attributes)
         self.query?.foundItemsHandler = { (items : [CSSearchableItem])
 -> Void in
             allItems.append(contentsOf: items)
         self.query?.completionHandler = { (error : NSError?) -> Void in
             for item in allItems {
                 let attributeSet = item.attributeSet
                 let foundTitle = attributeSet.title
                 let foundDisplayName = attributeSet.displayName
                 NSLog("title:\(foundTitle), displayName:\


Creating a Query Object

init(queryString: String, attributes: [String]?)

Initializes and returns a query object with the specified query string and item attributes.

var protectionClasses: [FileProtectionType]

An array of data protection classes that correspond to the protection classes associated with the indexed items.

Starting and Canceling a Query

func start()

Asynchronously queries the index for items that match the query object’s specifications.

func cancel()

Cancels a query operation.

var isCancelled: Bool

A Boolean value that indicates if the query has been cancelled.

Handling Query Results

var completionHandler: ((Error?) -> Void)?

The block to execute when the query completes.

var foundItemCount: Int

The number of items found so far.

var foundItemsHandler: (([CSSearchableItem]) -> Void)?

The block to execute when the query finds a new batch of matching items.


enum CSSearchQueryError.Code

Error codes that describe reasons for which a query might fail.


Inherits From

Conforms To

Beta Software

This documentation contains preliminary information about an API or technology in development. This information is subject to change, and software implemented according to this documentation should be tested with final operating system software.

Learn more about using Apple's beta software