【发布时间】:2017-09-14 16:24:48
【问题描述】:
我无法使用 MDQuery 在 Swift 3 中探索 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 mojo 无法正常工作(坦率地说,我一直觉得这很令人困惑)。
如何将此 UnsafeRawPointer 转换为可以成功调用 MDItemCopyAttribute 的东西?
替代品
我可以通过将我的 Objective-C 代码放入一个 Objective-C 帮助对象并从 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 怎么样? -
@JAL 结果与
bindMemory相同。我也尝试将它们一起使用,以防万一。 :) -
嗯,不错,值得一试。我猜你为什么得到
NSAtom是因为你的ptr变成UnsafePointer(0x1),得到pointee相当于调用(id)0x1之类的东西__NSAtom.我会继续挖掘。 -
我会假设你必须通过
Unmanaged<MDItem>.fromOpaque(...)——但我不知道MDQuery是如何工作的,所以无法测试它。 -
@Hamish 我会试试的!当然,我也可以发布更多代码。等一下。