"Generic macOS" Icon In Asset Catalog NSImage Picks Smallest Representation on 10.12.6 Compiled Under Xcode 9

I have a image that gets loaded from an asset catalog. It is a "generic macOS icon" so it gets compiled to an icns and I provide an image for all the sizes (16, 32, 32@2x, 128, 256, 512, 512@2x).


I've been using this for awhile and never had issue. I'm about to put out an update, and I notice on 10.12.6 NSimageView picks a terribly small representation and upscales it (the image looks blurry). The NSImageView is set to scale proportionally up or down. This always worked, and on 10.13 it still does but on 10.12.6 it seems the last update has this bug.


Also, in another part of my app, I draw the image in a custom CALayer. I use CGImageForProposedRect:context:hint: and pass in the bounds of the layer and draw it in the context, and I also get an incredibly small representation on 10.12.6.


I have to place the largest image as a standalone image in the asset catalog and downscale it on 10.12.6 now. Anyone know if there is a "better" workaround to tease the API to pick a better image representation on 10.12.6?

Replies

There seems to be more backward compatibility issues related to Asset Catalogs when using Xcode 9. I have a single scale vector image in an asset catalog and my the app will crash on launch on El Capitan (as soon as I try to access this image). Crash log seems to indicate that the image can't be found in the asset catalog by its name, and the system calls CFRelease and passes in NULL, causing the crash.


So I now added a separate bitmap version of the image and use that one at runtime on El Capitan. Would like to avoid stuff like this, if possible. Weren't single scale images introduced in Xcode 6?

There are a lot of moving parts in what you describe. For example, you're comparing 10.13 and 10.12.6, but are they running on the same physical hardware? (Specifically, if you're running 10.12.6 under virtualization, which is a common way to test older macOS versions, your results may not be comparable.) I've been trying to think where to look for some sort of API contract about which of the icon representation should get chosen for the image view, but I can't think of any documentation that covers that.


I suggest you write some code to iterate through the representations in the NSImage you get by loading the icon manually. Are all the representations present in both cases? For icons in the 10.12.6 Finder, which of the representations is it using for small icon sizes, and it is using the same ones in 10.13?


If I understand correctly what you're doing here, I think I might suggest for all modern Macs that you put an image (the highest-resolution of the icon representations) in your asset catalog, rather than an icon set, and let that get scaled up or down for the image view. This may produce slightly different results from what (say) the Finder shows, but the smallest icon sizes are really kinda irrelevant now, since they were for much lower resolution displays than we currently have. That would be more of an end-run around your problem than a direct solution.


Regarding the vector image, it's been possible for a long time to give Xcode a vector image, but the ability to keep it in vector form in the built bundle is quite new. (Wasn't it introduced at WWDC 2016?) It may well be incompatible with 10.11 or earlier. You might double-check that you've specified the correct target version for the storyboard or XIB in the IB inspector, or you may need to force it to use an older asset catalog format if that's possible. Again, it's not clear where in the documentation to go to find out what macOS runtimes support what features here.


Also, re-check the Xcode 9.0, 9.1 and 9.2 release notes for anything about bugs in asset catalogs. I have a vague recollection of a couple of things being fixed or noted as broken in there.

>Regarding the vector image, it's been possible for a long time to give Xcode a vector image, but the ability to keep it in vector form in the built bundle is quite new. (Wasn't it introduced at WWDC 2016?) It may well be incompatible with 10.11 or earlier. You might double-check that you've specified the correct target version for the storyboard or XIB in the IB inspector, or you may need to force it to use an older asset catalog format if that's possible. Again, it's not clear where in the documentation to go to find out what macOS runtimes support what features here.


I'm not sure if there is a way to force Xcode to use an older asset catalog format? I'm aware of such a feature for xibs/storyboards but is it possible to do with asset catalogs? The image is not loaded in IB, I use NSImage +imageNamed:. I ended up providing a fallback non-vector image and fallback to it on 10.11. This avoids this crash on 10.11.


>There are a lot of moving parts in what you describe. For example, you're comparing 10.13 and 10.12.6, but are they running on the same physical hardware? (Specifically, if you're running 10.12.6 under virtualization, which is a common way to test older macOS versions, your results may not be comparable.)


In the case of the icns images (generic Mac icon in asset catalog, which creates an icns) it now no longer working as expected when the app is compiled on Xcode 9 (I've had these icons in my asset catalog prior to the release of Xcode 9 and they haven't been changed in awhile and it worked before), it seems the smallest representation is used. I tried to explicitly set the NSImage size to a high value using setSize: and passing in 1024x1024 but the NSImageView appears to still be upscaling a small representation and it looks bad. And in the case of drawing it in a CALayer context, use of CGImageForProposedRect gives me the smallest representation (looks like the 32 point size one).


I haven't been able to run it in the Xcode debugger on 10.12 yet, but my guess is the image loaded from the asset catalog isn't picking up all the representations on 10.12 and earlier, I think they must have changed something that broke the image loading for these resources on 10.12 and earlier. On 10.13 with the exact same image and code, I get the desired behavior I got prior to Xcode 9; the best representation is used when drawn by NSImageView and my CALayer.


To clarify about hardware, I have an iMac still running 10.12 (not testing in a virtual machine) and the small image problem happens. My testing for 10.11 was done on my Macbook Pro in VirtualBox though. Generic icon problem happens in both cases.