我在使用Swift 3和MDQuery进行Spotlight搜索结果探索时遇到了一些问题。我期望MDQueryGetResultAtIndex
返回一个MDItem,而在C/Objective-C中,这个假设是成立的,并且我可以调用MDItemCopyAttribute
来探索该项。例如,在这里,我成功获取了找到项的路径名:
MDItemRef item = (MDItemRef)MDQueryGetResultAtIndex(q,i);
CFStringRef path = MDItemCopyAttribute(item,kMDItemPath);
但在Swift 3中,MDQueryGetResultAtIndex
返回一个UnsafeRawPointer!
(在C中是指向void的指针)。为了克服这一点,我尝试过以下方法:
if let item = MDQueryGetResultAtIndex(q, 0) {
let ptr = item.bindMemory(to: MDItem.self, capacity: 1)
let path = MDItemCopyAttribute(ptr.pointee, kMDItemPath)
}
但是它崩溃了,日志显示ptr.pointee
是一个NSAtom。很明显,我的个人UnsafeRawPointer技巧不起作用(坦白地说,我一直觉得这很困惑)。
我应该如何将这个UnsafeRawPointer转换成我可以成功调用MDItemCopyAttribute
的东西呢?
替代方案
我可以将我的Objective-C代码放入Objective-C helper对象中,并从Swift中调用它来解决这个问题;但我想编写一个纯Swift解决方案。
同样地,我可能会重新编写我的代码以使用更高级别的NSMetadataQuery,我也许会这么做;但是,我最初使用较低级别的MDQueryRef的Objective-C代码可以正常工作,所以现在我想知道如何将其直接转换为Swift。
完整代码:如果您想在家试试,请使用以下代码:
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) {
// ...
}
}
item?.assumingMemoryBound(to: MDItem.self)?.pointee
获取MDItem怎么样? - JALbindMemory
相同。我也尝试过将它们一起使用,以防万一。 :) - mattNSAtom
是因为你的ptr
变成了UnsafePointer(0x1)
,并且获取它的pointee
相当于调用类似(id)0x1
的东西,这是一个__NSAtom
。我会继续深入挖掘。 - JALUnmanaged<MDItem>.fromOpaque(...)
进行操作 - 但我不知道MDQuery
的工作原理,所以无法测试。 - Hamishvoid*
)引入到 Swift 中。我不会说它是错误地桥接了(除了类型安全漏洞外,将不透明指针返回给你并没有什么真正的问题)。根据我从MDQueryGetResultAtIndex
文档中的 理解,如果你想要通过提供自定义创建函数来获取自定义对象,那么就有可能得到自定义对象 - 所以我不认为 Swift 可以直接将其桥接回来作为MDItem
(因为它可能不是)。 - Hamish