How to read Finder icons (list with left source code) in OS X using Swift

I am trying to read information about the icons that appear in finder in the left list of sources. I have already tried NSFileManager

with the following parameters

  • NSURLEffectiveIconKey

    The reading icon is not the same as the finder
  • NSURLCustomIconKey

    - returns nil
  • NSURLThumbnailKey

    - returns nil
  • NSThumbnail1024x1024SizeKey

    - returns nil

I was able to read all mounted devices using NSFileManager, but I don't know how to read device related icons? Perhaps someone has some idea or hint.

I have also tried using

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

      

but it returns the same image as NSURLEffectiveIconKey

Thank!

+3


source to share


3 answers


This answer is a Swift 1.2 translation of Ken Thomases Objective-C answer .

All credits go to Ken Thomas, this is just a translation of his amazing answer.

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 ...
    }
}

      

Explanations:

When translating Ken's answer from Objective-C to try and use it, I ran into some difficulties, so I made this answer.

The first problem was with LSSharedFileListCreate

, the signature of a method in Swift did not accept nil

as its first parameter. I had to find a constant representing a CFAllocator

: kCFAllocatorDefault

. And I didn't accept the third parameter either nil

, so I put a dummy unused NSMutableDictionary to keep the compiler happy.

Also the "seed" parameter LSSharedFileListCopySnapshot

did not accept the usual var seed:Uint32?

for inout, I had to specify a default seed

.

For deciding when to use takeRetainedValue

or takeUnRetainedValue

when using these APIs, I titled this answer .



Finally, I had to LSSharedFileListItemRef

serve the returned array as a Swift array of elements (it was originally inferred as a CFArray by the compiler).

Update

This is deprecated in OS X El Capitan 10.11 (thanks @patmar)

enter image description here

Update 2

Please note that while it is deprecated it still works. The cast as [LSSharedFileListItemRef]

in the previous solution is now ignored, so we have to use it as NSArray

and then cast the element later:

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

    }
}

      

+3


source


First, the correct way to query volumes is displayed in the Finder sidebar using the LSSharedFileList API. This API also provides the ability to request an icon:

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);
}

      



You can query other properties of elements using LSSharedFileListItemCopyDisplayName()

, LSSharedFileListItemCopyResolvedURL

and LSSharedFileListItemCopyProperty()

.

+7


source


NSURLCustomIconKey will return zero because support for this key is not implemented. It is mentioned in the title, but not in the NSURL documentation. You can get information through the legacy File Manager methods.

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

Alternatively there could be something like this.

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

      

Parameters
value The
location where the value of the property of the resource identified by the key should be stored.

The name of one of the properties of the URL resource.
Error An
error occurred when the resource could not be restored. This parameter is optional. If you are not interested in getting information about the error, you can pass null.

0


source







All Articles