NSImageView not working? - objective-c

I am trying put an image in a view. This is my code:
NSImageView *imView = [[NSImageView alloc] initWithFrame:NSMakeRect(0, 0, 480, 360)];
NSImage *myImage = [[NSImage alloc] initByReferencingFile:#"image.png"];
[imView setImage:myImage];
[theView addSubview:imView];
[window setContentView:theView];
But the window is blank(image doesn't get drawn). If I place a textfield in the view for example.. it works perfectly, but not NSImageView...I checked the console and there's no warning/error messages...
Thanks!

Since [imView isValid] returns false, this means that NSImage hasn’t been able to create an image based on that file. A common reason is that the file couldn’t been located. From the documentation of -initByReferencingFile:,
filename
A full or relative path name specifying the file with the desired image data. Relative paths must be relative to the current working directory.
This means that the behaviour of -initByReferencingFile: depends on the current directory, and ideally you should pass the full path name.
A better solution is to use +imageNamed: instead because of two reasons: it uses an image cache and it is able to look for a file inside the application bundle.

Related

Why can't I load an image which is located in the assets catalog?

I am trying to build a simple screensaver. The first thing I do is to load the image from the asset catalog with the method [NSImage imagedNamed:] which returns a nil value, that would mean that it can't find the image. When I try to load the image directly from the bundle with the method
[[NSBundle mainBundle] URLForImageResource:]
I also get a nil value. I don't understand why this happens. The image is located in the asset catalog and in the project settings I have set it as a bundle resource.
You can access images in asset catalogs by name, however not using the imageNamed: method of NSImage -
Instead you can query a bundle for image resources of specific name, e.g. to find an image in the bundle of the class requesting the image you would:
NSBundle *bundle = [NSBundle bundleForClass:[self class]];
NSImage *myImage = [bundle imageForResource:#"MyImageName"];
where MyImageName refers to the name you assigned the image in your asset catalog.
After I continued searching on the internet I found out that the screensaver is executed as some kind of plugin and by loading the main bundle I loaded the System Preference bundle which means that I am not able to get my resource by loading the main bundle, instead I have to load the bundle with bundleIdentifier or with the path where the bundle is saved.
So my code looks like this now:
NSBundle*bundle=[NSBundle bundleWithIdentifier:#"com.myname.APOD"];
NSImage*image=[[NSImage alloc] initWithContentsOfFile:[bundle pathForResource:#"appimage" ofType:#"png"]];

How to get suitable CGImage from combined TIFF for display scale

I have two PNGs in a Mac project. Normal and #2x. Xcode combines these into a single TIFF with the #2x being at index 0 and the #1x at index 1.
What is the suggested approach to get the appropriate image as CGImageRef version (for use with Quartz) for the current display scale?
I can get the image manually via CGImageSource:
NSBundle *mainBundle = [NSBundle mainBundle];
NSURL *URL = [mainBundle URLForResource:#"Canvas-Bkgd-Tile" withExtension:#"tiff"];
CGImageSourceRef source = CGImageSourceCreateWithURL((__bridge CFURLRef)(URL), NULL);
_patternImage = CGImageSourceCreateImageAtIndex(source, 1, NULL); // index 1 is #1x, index 0 is #2x
CFRelease(source);
I also found this to be working, but I am not certain that this will return the Retina version on a Retina display:
NSImage *patternImage = [NSImage imageNamed:#"Canvas-Bkgd-Tile.tiff"];
_patternImage = [patternImage CGImageForProposedRect:NULL context:nil hints:nil];
CGImageRetain(_patternImage); // retain image, because NSImage goes away
An acceptable answer to this question either provides a solution how to get the CGImage suitable from a combined multi-resolution TIFF, or explains why the second approach here is working. Or what changes are required.
I am opting to answer on "why the second approach here is working".
In one of the WWDC videos published since 2010, they said that :
+[NSImage imageNamed:] chooses the best image representation object available for the current display.
So chances are that you are calling this class method from within a locked focus context (e.g. within a drawRect: method or similar), or maybe you actually called lockFocus yourself. Anyway, the result is that you get the most suitable image. But only when calling +[NSImage imageNamed:].
EDIT: Found it here:
http://adcdownload.apple.com//wwdc_2012/wwdc_2012_session_pdfs/session_213__introduction_to_high_resolution_on_os_x.pdf
Search for the keyword "best" in the slides: "NSImage automatically chooses best representation […]".
So, your second version will return the Retina version on a Retina display, you can be certain of it, it is advertised in the documentation[*].
[*] This will only work if you provide valid artwork.

Setting Path of UIImage

I would like to know how to set the path (into folders) of a UIImage when I'm doing something like this:
[UIImage imageNamed:#"Sprites/Macbeth/Climbing/1.png"];
I want to to have it use the image entitled "1.png" in the folder Sprite, in that folder in Macbeth and in that folder Climbing. I want to be able to do that with one line of code since I have a lot of UIImages like that for sprite animations (all in arrays). Does anyone know how to do this? Thanks in advance!
iOS does not maintain the folder system you have. So this isn't possible. You would pull your image simply using this line of code.
[UIImage imageNamed:#"1.png"];
Instead of trying to nest folders try putting that into the file name like macbeth-climbing-1.png if you need to classify multiple 1.png's
Write a method or function that does the following:
Call [NSBundle mainBundle] to get your application bundle
Call -[NSBundle pathForResource:ofType:inDirectory:] to get the path to the image
Call +[UIImage imageWithContentsOfFile:] with that path

Using Interface Builder's System Media files in code

I have a question regarding the several images and sound files in the Media tab of IB's library: how can they be used in code?
I want change the image of a NSImageVew to NSRevealFreestandingTemplate, but how can I access it? I'm pretty sure there must be a better way than creating a hidden image view and pulling it from there. Any ideas?
Thank you!
Use NSImage's imageNamed: method to get system images. You can use any of the values found in NSImage's Constants section as the name. To get the image you specified, you would use:
[NSImage imageNamed: NSImageNameRevealFreestandingTemplate];
[imageView setImage:[NSImage imageNamed:#"NSRevealFreestandingTemplate"]];

Changing an NSImage in XCode - this line of code not working

I am having a problem that is eating me alive. I really hope I am just missing something small here. It appears to be a rather "n00b" issue.
I have a blank NSImageView that I want to display a picture when a button is pressed — simple as that.
Here is my line of coding
NSBundle *mb = [NSBundle mainBundle];
NSString *fp = [mb pathForResource:#"tiles" ofType:#"PNG"];
NSImage *image = [[NSImage alloc] initWithContentsOfFile:fp];
if ( [image isValid] ) {
[selection setImage:image];
[selection setImageScaling:NSScaleProportionally];
}
Whereas,
tiles.PNG is a resource in my bundle
and if [image isValid] is satisfied, because I've inserted dummy code into the clause and had that work
selection is defined in my header file as follows
IBOutlet NSImageView *selection;
It is also linked up to the application delegate in IB.
I have a feeling I might not be linking it properly?
WHy wouldn't the image display? If anyone can see an error - or provide me with working code - I would be soooooo thankful
Brian
It's not a linking issue—your app wouldn't even launch (assuming it even links successfully) if you'd failed to link against Cocoa or AppKit.
More probably, either you haven't connected the outlet to your image view in your nib, or you haven't loaded the nib yet. The way to check this would be to NSLog the value of the imageView pointer, using the %p formatter.
I had a similar issue where my view wasn't displaying, and it turned out that the view was hidden. This was a setting in the view properties in Interface Builder. Just a punt, but give it a go.
You need to use the debugger and see what's going on as it runs. Is fp nil? Is image nil? Is selection nil? The debugger is your friend.
did you remember to send -setNeedsDisplay to the NSImageView after you set the image?