Wednesday, September 21, 2011

Displaying a UIImage in a UIViewController




Ok, yesterday we managed to get the "NextLevel" view flow logic working. Now, we're going to see if we can't go ahead and add an image to it.

Ok, let's take a look at the class reference:

http://developer.apple.com/library/ios/#DOCUMENTATION/UIKit/Reference/UIImageView_Class/Reference/Reference.html

An image view object provides a view-based container for displaying either a single image or for animating a series of images.

// ok

For animating the images, the UIImageView class provides controls to set the duration and frequency of the animation. You can also start and stop the animation freely.

// don't need to worry about that right now

New image view objects are configured to disregard user events by default. If you want to handle events in a custom subclass of UIImageView, you must explicitly change the value of the userInteractionEnabled property to YES after initializing the object.

// don't need to worry about that either

When a UIImageView object displays one of its images, the actual behavior is based on the properties of the image and the view.


If either of the image’s leftCapWidth or topCapHeight properties are non-zero, then the image is stretched according to the values in those properties.

Otherwise, the image is scaled, sized to fit, or positioned in the image view according to the contentMode property of the view.

// what is the content mode property?

It is recommended (but not required) that you use images that are all the same size. If the images are different sizes, each will be adjusted to fit separately based on that mode.

All images associated with a UIImageView object should use the same scale.

If your application uses images with different scales, they may render incorrectly.


Ok, good intro, but I'd really just like to see some example code.

It looks like I'll be using this initWithImage method:

initWithImage:

Returns an image view initialized with the specified image.
- (id)initWithImage:(UIImage *)image
Parameters

image

The initial image to display in the image view.

Return Value

An initialized image view object.


I won't need this:

initWithImage:highlightedImage:

Returns an image view initialized with the specified regular and highlighted images.
- (id)initWithImage:(UIImage *)image highlightedImage:(UIImage *)highlightedImage
Parameters

image

The initial image to display in the image view.
highlightedImage

The image to display if the image view is highlighted.


Ok, this thread looks like it will help out:

http://www.iphonedevsdk.com/forum/iphone-sdk-development/5573-cant-get-uiimageview-load-uiimage-runtime.html


Here's what the OP said worked for him:

- (void)viewDidLoad {



//taken from http://idevkit.com/forums/tutorials-code-samples-sdk/3-one-line-uiimage-url.html
UIImage *img = [[UIImage imageWithData: [NSData dataWithContentsOfURL: [NSURL URLWithString: @"http://someserver.com/somefile.jpg"]]] retain];
if (img != nil) { // Image was loaded successfully.
[imgView setImage:img];
[imgView setUserInteractionEnabled:NO];
[img release]; // Release the image now that we have a UIImageView that contains it.
}
[super viewDidLoad];
}



Ok, we can try that for now, and switch to a file later. Let's fina a url with an image...wow, that was amazingly difficult - I finally just ftp'd into my own sight.

http://kanjisoft.com/appimages/correct_answer.png

So the above code becomes like this:



UIImage *img = [[UIImage imageWithData: [NSData dataWithContentsOfURL: [NSURL URLWithString: @"http://kanjisoft.com/appimages/correct_answer.png"]]] retain];
if (img != nil) { // Image was loaded successfully.
[imgView setImage:img];
[imgView setUserInteractionEnabled:NO];
[img release]; // Release the image now that we have a UIImageView that contains it.
}
[super viewDidLoad];


Ok, so let's try this:


- (void)viewDidLoad
{

UIImage *img = [[UIImage imageWithData: [NSData dataWithContentsOfURL: [NSURL URLWithString: @"http://kanjisoft.com/appimages/correct_answer.png"]]] retain];
if (img != nil) { // Image was loaded successfully.
[imageView setImage:img];
[imageView setUserInteractionEnabled:NO];
[img release]; // Release the image now that we have a UIImageView that contains it.
}

[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}


Good - we get the following image:




Ok, now let's figure out how to load it from a file.




UIImage *img = [[UIImage imageWithData: [NSData dataWithContentsOfURL: [NSURL URLWithString: @"http://kanjisoft.com/appimages/correct_answer.png"]]] retain];



Let's look up UIImage.

This method looks hopeful:

ImageWithContentsOfFile:

Creates and returns an image object by loading the image data from the file at the specified path.
+ (UIImage *)imageWithContentsOfFile:(NSString *)path
Parameters

path

The full or partial path to the file.

Return Value

A new image object for the specified file, or nil if the method could not initialize the image from the specified file.
Discussion

This method does not cache the image object.


This url offers a pretty good idea:

http://www.ericd.net/2009/07/iphone-previous-example-with-touches.html

UIImage *img = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"image_1.jpg" ofType:nil]];


So, does this mean I just need to put an image in the resource folder?

Heres another example that separates the creation of the path from:

http://www.iphonedevsdk.com/forum/iphone-sdk-development/34543-can-someone-please-show-me-how-do-imagewithcontentsoffile-method.html




NSString* imagePath = [ [ NSBundle mainBundle] pathForResource:@"workpaper" ofType:@"png"];

imageView.image = [ UIImage imageWithContentsOfFile: imagePath];



So now we've culled it down to this "pathForResource". What is that, a parameter of NSBundle?

Let's look at the overview of NSBundle:



An NSBundle object represents a location in the file system that groups code and resources that can be used in a program.

NSBundle objects

locate program resources,

dynamically load and unload executable code,

and assist in localization.


You build a bundle in Xcode using one of these project types:

Application, Framework, plug-ins.

Although bundle structures vary depending on the target platform and the type of bundle you are building, the NSBundle class hides this underlying structure in most (but not all) cases.

Many of the methods you use to load resources from a bundle automatically locate the appropriate starting directory and look for resources in known places.

For information about application bundle structures (for Mac OS X and iOS), see Bundle Programming Guide.

// Bundle programming guide? Seriously?

For information about the structure of framework bundles, see Framework Programming Guide.

// Ugh.

For information about the structure of Mac OS X plug-ins, see Code Loading Programming Topics.

// Yeah, I'm all over it.

For additional information about how to load nib files and images in a Mac OS X application, see NSBundle Additions Reference.

// Good Christ.

For information about how to load nib files in an iOS application, see NSBundle UIKit Additions Reference.

Unlike some other Foundation classes with corresponding Core Foundation names (such as NSString and CFString), NSBundle objects cannot be cast (“toll-free bridged”) to CFBundle references.

// huh? toll-free bridged? What was wrong with "cast"?

If you need functionality provided in CFBundle, you can still create a CFBundle and use the CFBundle Reference API. See “Interchangeable Data Types” for more information on toll-free bridging.

// Sigh.



Ok, as far as I can tell it's a thing for identifying resources that has a lot of guides.

Let's just copy an image file into the resources group of the project from finder, and then try this:

#pragma mark - View lifecycle

- (void)viewDidLoad
{

NSString* imagePath = [ [ NSBundle mainBundle] pathForResource:@"fragile_as_snow" ofType:@"png"];


UIImage *img = [ UIImage imageWithContentsOfFile: imagePath];

if (img != nil) { // Image was loaded successfully.
[imageView setImage:img];
[imageView setUserInteractionEnabled:NO];
[img release]; // Release the image now that we have a UIImageView that contains it.
}

[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}


Ok, it works. Heres an image:


No comments:

Post a Comment