[macOS] CoreSpotlight importer using CSImportExtension failing to index

I've been trying to add a CoreSpotlight indexer to my macOS application. The new template for the indexer uses the new appex CSImportExtension style importer.

I've been following this ->

https://developer.apple.com/documentation/corespotlight/csimportextension

  1. I changed the CSSupportedContentTypes in the Info.plist file to the correct file type uti.
  2. I added a dummy value into the attributes (see code below) - just setting contentDescription to 'noodle' (easy to search for)
class ImportExtension: CSImportExtension {
   override func update(_ attributes: CSSearchableItemAttributeSet, forFileAt: URL) throws {
      // Add a dummy value, and see whether spotlight finds it
      attributes.contentDescription = "noodle"
   }
}
  1. I have a number of files on disk that match the uti (and can be found when I search by the file name)

Yet, when I build and run my app, the a spotlight search for 'noodle' finds no results.

Can anyone give me any advice? I cannot find any indication that the ImportExtension is called (although when I put a log message at the start of the update() call there's no message in the console which seems to suggest it's not being called).

Is there any way of debugging this?

Cheers and thanks -- Darren.

Answered by DTS Engineer in 859277022

As more formal confirmation, CSImportExtension does not function on macOS and never has. Multiple bugs have been filed on both the extension point and the documentation, but until something changes in the system, the only option is to use the old MDImport API. You can find more information on that in the "Spotlight Importer Programming Guide" from the documentation archive.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Btw I've tried this using Xcode 12, Xcode 13 beta, macOS 12 and macOS 13 beta. No luck with any combo

I cannot find any indication that the ImportExtension is called

That’s my experience. I researched this in gory detail as part of a DTS TSI and my conclusion was that Core Spotlight importer extensions just don’t work on the Mac )-:

While we have a bug on file about this (r. 91288903), I would appreciate you filing your own bug based on your recent experience.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Thanks for the update mate. I have filed FB11490572 as you've mentioned.

Frustrating, but lets hope it can get some eyeballs on it.

In case it helps anyone, with some effort I was able to write a MDImporter plugin in Swift: https://github.com/foxglove/MCAPSpotlightImporter

It would’ve been much nicer to write it as a CSImportExtension, and it does seem that mdimport on macOS has some references to “modern importers” (see mdimport -help), but as mentioned above, I wasn’t able to get CSImportExtensions to work at all on macOS. I saw some logs related to them so it seems like it is partially implemented, but somehow broken.

The Swift MDImporter will work as a stand-in for now, but I look forward to replacing it someday!

Just wanted to update this thread with current information. I'm currently building a CSImportExtension and got it to run on macOS 15.0. So at some point this was fixed.

At first I could not get it to run, but then I noticed that when running the mdimport debug commands, the type identifier is all lowercase, even though the identifier we defined in our application has some uppercase letters. So while our document identifier is actually "com.company.someFile", in the Info.plist of the CSImportExtension we had to define it as "com.company.somefile" for it to be run.

Also be aware: While the mdimport -d3 command for testing will say something like: Imported 'foo/bar/xxxx.ext' of type 'com.company.somefile' with no plugIn, the plugin is being called just fine.

I filled a documentation suggestion FB20301430 Remove macOS 12.0+ from list of supported OS for CSImportExtension.

Since it doesn't work I think this would save developers from wasting time trying.

As more formal confirmation, CSImportExtension does not function on macOS and never has. Multiple bugs have been filed on both the extension point and the documentation, but until something changes in the system, the only option is to use the old MDImport API. You can find more information on that in the "Spotlight Importer Programming Guide" from the documentation archive.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

the only option is to use the old MDImport API.

If you look around for old school Spotlight importer plug-in samples, you’ll find a lot of really weird code out there. If you decide to implement a Spotlight importer plug-in and are interested in using new tools and techniques — like Swift! — please post a follow-up here and I can offer some suggestions on how to proceed.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

I'd really like to have a way to integrate with Spotlight in the interim.

Understood.

I supported Spotlight importers back in the day, and as part of that I created infrastructure to make the whole task easier. I never got around to shipping that as sample code that because I expected CSImportExtension would come online and make it redundant. It seems like I was overly optimistic )-:

My code was written in Objective-C, but I spent yesterday converting it to Swift [1]. There are two parts to this:

  • QCFPlugIn — This is a generic mechanism for building different types of CFPlugIn implementations [2].
  • QSpotlightPlugIn — A type-specific subclass that handles Spotlight.

To use this, subclass QSpotlightPlugIn:

private final class MySpotlight: QSpotlightPlugIn {
    
    override func importFrom(_ url: URL, type contextTypeUTI: UTType, updating attributes: NSMutableDictionary) throws {
        … your code here …
    }
}

and then invoke the infrastructure from your entry point:

@_cdecl("MySpotlightFactory")
func MySpotlightFactory(allocator: CFAllocator, typeUUID: CFUUID) -> UnsafeMutableRawPointer? {
    let factoryUUID = UUID(uuidString: "… your UUID …")!
    return MySpotlight.makeInstance(factoryID: factoryUUID)
}

#if swift(>=6.3)
    #warning("Check to see if SE-0495 has landed.")
#endif

Note This uses the non-standard @_cdecl attribute. You should be able to switch to a standard attribute once SE-0495 lands.

This code is really gnarly. I’ve done by best to write it carefully and to test it at my desk (including automated testing with Zombies and ASan). However, it’s not been tested in the real world, so if you decide to use it then that burden falls on you.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] The fact that the Swift code relies on subclassing reflects its Objective-C heritage.

[2] I originally wrote this for Quick Look plug-ins. Fortunately those have been replaced.

[macOS] CoreSpotlight importer using CSImportExtension failing to index
 
 
Q