2

I am having trouble trying to create an NSCollectionView with icons that are taken from Finder's icon preview.

Ideally, if the file is a dmg it should display the hard drive icon, an mp3 should be the mp3 icon and a photo should display what the photo looks like itself.

There is one post that addresses this issue: Is it possible to get programmatic access to finder preview images?

But the code is old and does not compile. I am also using Swift in this project.

I used this post to setup a template for my project: Is there a way to set up a NSCollectionView programmatically in Swift?

Which adds a subview to NSView. If this can be modified to implement the icons, that would be ideal.

In addition I am using a NSFileManager.defaultManager to get the contents of a folder, and would like to display those contents in the collection view.

I am new to developing on the Mac platform and have more experience with iOS, specific answers are much appreciated, thanks!

Community
  • 1
  • 1

2 Answers2

1

Update, I was able to figure out how to use what Finder uses with the Quicklook library that Apple provides. Here is part of the code that I used. Note that if you are trying to use Quicklook on a file that does not have a preview, then there will be an error, so in those cases I just used the iconForFile function (below this code block)

let tmp = QLThumbnailImageCreate(kCFAllocatorDefault, tmpURL , CGSize(width: 64, height: 64), nil)
tmpImage = tmp.takeUnretainedValue()
tmpIcon = NSImage(CGImage: tmpImage!, size: NSSize(width: 64, height: 64))

Original:

I was able to find (almost) what I was looking for.

In the NSWorkspace class there is a method

func iconForFile(_ fullPath: String) -> NSImage

That will return an NSImage of the icon. Unfortunately, I do not see a way to get a preview of the image if it is a picture. Nor do I see a way to make the picture larger (only 32x32 pixels).

Hopefully this answer will help others that encounter this problem!

0

I've used your code from your answer but I noticed that it did not keep the file's aspect ratio and the low res version would just be the downsampled high res version. So based on your answer, here's my solution:

let imageLowResRef = QLThumbnailImageCreate(kCFAllocatorDefault, url as CFURL , CGSize(width: 32, height: 32), nil)

guard imageLowResRef != nil else {
    return NSWorkspace.shared.icon(forFile: url.path)
}

let image = NSImage()
let imageLowRes = imageLowResRef!.takeUnretainedValue()
image.addRepresentation(NSBitmapImageRep(cgImage: imageLowRes))

let imageHighResRef = QLThumbnailImageCreate(kCFAllocatorDefault, url as CFURL , CGSize(width: imageLowRes.width*2, height: imageLowRes.height*2), nil)
let imageHighRes = imageHighResRef!.takeUnretainedValue()
image.addRepresentation(NSBitmapImageRep(cgImage: imageHighRes))

Edit: If you add let options = [kQLThumbnailOptionIconModeKey: true] as CFDictionary, you get to the options parameter, you get the preview rendered as icons.

Daniel
  • 1,473
  • 3
  • 33
  • 63