【问题标题】:How to read Finder icons (left source list) on OS X using Swift如何使用 Swift 在 OS X 上读取 Finder 图标(左侧源代码列表)
【发布时间】:2015-07-31 22:59:29
【问题描述】:

我尝试阅读有关在左侧源列表的查找器中显示的图标的信息。我已经尝试过NSFileManager 有以下选项

  • NSURLEffectiveIconKey图标读取与finder中的不一样
  • NSURLCustomIconKey - 返回零
  • NSURLThumbnailKey - 返回零
  • NSThumbnail1024x1024SizeKey - 返回零

我设法使用 NSFileManager 读取了所有已安装的设备,但我不知道如何读取与设备连接的图标?也许有人有任何想法或提示。

我也试过

var image: NSImage = NSWorkspace.sharedWorkspace().iconForFile((url as! NSURL).path!)

但它返回与NSURLEffectiveIconKey相同的图像

谢谢!

【问题讨论】:

    标签: macos swift cocoa


    【解决方案1】:

    首先,查询 Finder 侧栏中显示哪些卷的正确方法是使用 LSSharedFileList API。该 API 还提供了一种查询图标的方法:

    LSSharedFileListRef list = LSSharedFileListCreate(NULL, kLSSharedFileListFavoriteVolumes, NULL);
    UInt32 seed;
    NSArray* items = CFBridgingRelease(LSSharedFileListCopySnapshot(list, &seed));
    CFRelease(list);
    for (id item in items)
    {
        IconRef icon = LSSharedFileListItemCopyIconRef((__bridge LSSharedFileListItemRef)item);
        NSImage* image = [[NSImage alloc] initWithIconRef:icon];
    
        // Do something with this item and icon
    
        ReleaseIconRef(icon);
    }
    

    您可以使用LSSharedFileListItemCopyDisplayName()、LSSharedFileListItemCopyResolvedURL和LSSharedFileListItemCopyProperty()查询项目的其他属性。

    【讨论】:

    • 太棒了!我已经制作了一个 Swift 版本,如果我将它作为答案发布并注明您的帖子的来源,您可以吗?不确定这是否是正确的方法......
    • 我不确定这是否有礼节。来吧。
    • 完成(编辑了我之前的答案)。非常感谢。如果您以后觉得这是一个坏主意,请联系我,我会删除它。
    【解决方案2】:

    这个答案是 Ken Thomases's Objective-C answer 的 Swift 1.2 的翻译。

    所有功劳归于 Ken Thomases,这只是他出色答案的翻译。

    let listBase = LSSharedFileListCreate(kCFAllocatorDefault, kLSSharedFileListFavoriteVolumes.takeUnretainedValue(), NSMutableDictionary())
    let list = listBase.takeRetainedValue() as LSSharedFileList
    
    var seed:UInt32 = 0
    let itemsCF = LSSharedFileListCopySnapshot(list, &seed)
    
    if let items = itemsCF.takeRetainedValue() as? [LSSharedFileListItemRef] {
        for item in items {
            let icon = LSSharedFileListItemCopyIconRef(item)
            let image = NSImage(iconRef: icon)
            // use image ...
        }
    }
    

    解释:

    在从 Objective-C 翻译 Ken 的答案以尝试使用它时,我遇到了一些困难,这就是我做出这个答案的原因。

    第一个问题是LSSharedFileListCreate,Swift 中的方法签名不接受nil 作为它的第一个参数。我必须找到一个代表CFAllocator 的常量:kCFAllocatorDefault。第三个参数也不接受nil,所以我放了一个虚拟的未使用的 NSMutableDictionary 来让编译器满意。

    此外,LSSharedFileListCopySnapshot 的“种子”参数不接受通常的 var seed:Uint32? 用于 inout,我必须为 seed 提供默认值。

    为了决定在使用这些 API 时何时使用 takeRetainedValue 或 takeUnRetainedValue,我参考了 this answer。

    最后,我必须将返回的数组转换为 LSSharedFileListItemRef 元素的 Swift 数组(最初由编译器推断为 CFArray)。

    更新

    这已在 OS X El Capitan 10.11 中被弃用(感谢@patmar)

    更新 2

    请注意,虽然它已被弃用,但它仍然有效。在之前的解决方案中转换为 [LSSharedFileListItemRef] 现在已被忽略,因此我们必须转换为 NSArray,然后再转换该项目:

    if let items = itemsCF.takeRetainedValue() as? NSArray {
        for item in items {
            let icon = LSSharedFileListItemCopyIconRef(item as! LSSharedFileListItem)
            let image = NSImage(iconRef: icon)
            // use image ...
    
        }
    }
    

    【讨论】:

    • 感谢您的快速翻译
    • 不客气。一旦你有足够的代表,请不要忘记支持 Ken 的回答。 :) 没有他的回答,我无法制作我的版本。
    • 提示:iconRef 可以为 nil。就我而言,我得到了 icloud 图标的 nil 指针
    • 只是为了让你知道,我今天检查了 LSSharedList 的源代码,上面写着@available(OSX,introduced=10.5,deprecated=10.11,message="OS X 不再支持此功能。" ) public func LSSharedFileListCreate(inAllocator: CFAllocator!, _ inListType: CFString!, _ listOptions: AnyObject!) -> Unmanaged!
    • @patmar 尽管已被弃用,但它仍在进行一些修改(请参阅更新的答案)。
    【解决方案3】:

    NSURLCustomIconKey 将返回 nil,因为没有实现对这个键的支持。它在标题中提到,但在 NSURL 文档中没有。您可以通过已弃用的文件管理器方法获取信息。

    https://developer.apple.com/library/mac/documentation/Carbon/Reference/File_Manager/

    或者可能是这样的。

    func getResourceValue(_ value: AutoreleasingUnsafeMutablePointer<AnyObject?>,
               forKey key: String,
                error error: NSErrorPointer) -> Bool
    

    参数
    值
    应存储由 key 标识的资源属性的值的位置。
    key
    URL 的资源属性之一的名称。
    错误
    无法检索资源值时发生的错误。此参数是可选的。如果你对接收错误信息不感兴趣,你可以传递 nil。

    【讨论】:

    • 感谢您的回答。我正在使用 (url as! NSURL).getResourceValue(&value, forKey: NSURLVolumeNameKey, error: &error) 问题是我找不到返回像图标这样的查找器的键。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-19
    • 1970-01-01
    • 2023-04-02
    相关资源
    最近更新 更多