I'm having trouble exploring the results of a Spotlight search in Swift 3 using MDQuery. I expect MDQueryGetResultAtIndex
to yield an MDItem, and in C/Objective-C, that assumption works, and I can call MDItemCopyAttribute
on it to explore the item. Here, for example, I successfully get the pathname of a found item:
MDItemRef item = (MDItemRef)MDQueryGetResultAtIndex(q,i);
CFStringRef path = MDItemCopyAttribute(item,kMDItemPath);
But in Swift 3, MDQueryGetResultAtIndex
returns an UnsafeRawPointer!
(it's a pointer-to-void in C). To get past that, I've tried, for example:
if let item = MDQueryGetResultAtIndex(q, 0) {
let ptr = item.bindMemory(to: MDItem.self, capacity: 1)
let path = MDItemCopyAttribute(ptr.pointee, kMDItemPath)
}
but that crashes, and logging shows that ptr.pointee
is an NSAtom. It is quite evident that my personal UnsafeRawPointer mojo is not working (and to be frank I've always found this confusing).
How would I transform this UnsafeRawPointer into something I can successfully call MDItemCopyAttribute
on?
Alternatives
I can get over this hump by putting my Objective-C code into an Objective-C helper object and calling it from Swift; but I'd like to write a pure Swift solution.
Similarly, I could probably rewrite my code to use the higher-level NSMetadataQuery, and I may well do so; but my original Objective-C code using the lower-level MDQueryRef works fine, so now I'm curious how to turn it directly into Swift.
Complete code for those who would like to try this at home:
let s = "kMDItemDisplayName == \"test\"" // you probably have one somewhere
let q = MDQueryCreate(nil, s as CFString, nil, nil)
MDQueryExecute(q, CFOptionFlags(kMDQuerySynchronous.rawValue))
let ct = MDQueryGetResultCount(q)
if ct > 0 {
if let item = MDQueryGetResultAtIndex(q, 0) {
// ...
}
}