10

I'm working on a Yosemite app that includes a Notification Center widget (or Today extension). I have a framework where I'm storing all of my shared code and resources, which includes some images. Whether I just use PNGs or an asset catalog, they don't load if I just use the standard NSImage method imageNamed:. Looking at the documentation, that's clearly expected—it only looks in the main bundle.

On iOS, UIImage has a new method, imageNamed:inBundle:compatibleWithTraitCollection: that's perfeclty suited to this problem. I don't see anything similar for NSImage.

It seems like the best option is to do something like this:

[[NSBundle bundleForClass:[self class]] imageForResource:@"name"];

The main problem with this is that it doesn't use caching. In order to do that I added my own method in a category:

+ (NSImage *)imageNamed:(NSString *)name inBundle:(NSBundle *)bundle {
    NSImage *image = [NSImage imageNamed:name];
    if (image == nil) {
        image = [bundle imageForResource:name];
        [image setName:name];
    }
    return image;
}

This seems okay, but is there a better solution?

robotspacer
  • 2,732
  • 2
  • 28
  • 50
  • That doesn't seem too bad, it only adds 1 extra line of code (or a couple more if you have a few images to load) and you will still be able to use `imageNamed` without managing the images yourself. – TheAmateurProgrammer Aug 02 '14 at 13:27
  • 1
    Don't forget to support a case where `bundle` may be `nil`. In that case, use the main bundle. – Léo Natan Apr 08 '16 at 21:02

1 Answers1

4

There isn't currently API to do this in one method call, but I just filed radar://25632204 to request that +[NSImage imageNamed:inBundle:] be added for parity with UIKit.

Quinn Taylor
  • 44,553
  • 16
  • 113
  • 131