Defining an index for an image array in Objective C
I've been trying to figure out how to have a UIImageView with a next and previous button which when clicked will go to the next or previous image in the array. So far, here's what I have.
In my .h file I have declared:
IBOutlet UIImageView *imageView;
NSArray *imageArray;
And I also added:
-(IBAction) next;
In the .m file I have:
-(void) viewDidLoad;
{
imageArray = [[NSArray arrayWithObjects:
[UIImage imageNamed:@"1.png"],
[UIImage imageNamed:@"2.png"],
nil] retain];
}
Now here is where I'm struggling. I have the IBAction defined as follows in my .m:
-(IBAction)next
{
if (currentImage + 1 == [imageArray count])
{
currentImage = 0;
}
UIImage *img = [imageArray objectAtIndex:currentImage];
[imageView setImage:img];
currentImage++;
}
My problem is that I do not know where to define the currentImage index integer or how to define it. Is it in the header? The implementation? And how exactly do I declare it?
To be h开发者_开发问答onest I'm not even 100% sure the code I currently have is right, although I think if I can define the index, it will work.
Any advice?
This is how I would do it. (I've changed the name of a few instance variables: currentImage
sounds like it could be a pointer to an image (UIImage *) rather than just an integer value; adding Index
to the end makes that more clear. It may be obvious now that it's an integer, but when you revisit this code (or other code you write) in a month, it may be less obvious; or maybe that's just me)...
MDSlideshowController.h
:
#import <UIKit/UIKit.h>
@class MDBilboBaggins;
@interface MDSlideshowController : NSObject {
IBOutlet UIImageView *imageView;
NSArray *imageArray;
NSUInteger currentImageIndex;
BOOL someOtherVariable;
MDBilboBaggins *bilboBaggins;
// keep adding more instance variables as needed
}
- (IBAction)previous:(id)sender;
- (IBAction)next:(id)sender;
@end
MDSlideshowController.m
:
#import "MDSlideshowController.h"
#import "MDBilboBaggins.h"
// you could perhaps define currentImageIndex here, but see notes below:
// NSUInteger currentImageIndex = 0;
@implementation MDSlideshowController
// `currentImageIndex` is automatically initialized to 0 during init
// `someOtherVariable` is automatically initialized to 0 (NO) during init
-(void) viewDidLoad
{
imageArray = [[NSArray arrayWithObjects:
[UIImage imageNamed:@"1.png"],
[UIImage imageNamed:@"2.png"],
nil] retain];
[imageView setImage:[imageArray
objectAtIndex:currentImageIndex]];
}
- (IBAction)previous:(id)sender {
if (currentImageIndex == 0) {
currentImageIndex = [imageArray count] - 1;
} else {
currentImageIndex--;
}
[imageView setImage:[imageArray objectAtIndex:currentImageIndex]];
}
- (IBAction)next:(id)sender {
if (currentImageIndex + 1 >= [imageArray count]) {
currentImageIndex = 0;
} else {
currentImageIndex++;
}
[imageView setImage:[imageArray objectAtIndex:currentImageIndex]];
}
@end
Basically, you put instance variables right underneath the ones you've already defined. They can be of almost any type. You can use the types Cocoa Touch knows about, or classes you make yourself. In this example, I said that there was a special class named MDBilboBaggins
by using the @class MDBilboBaggins
statement. Then, I add the #import "MDBilboBaggins.h"
part in the .m file: this can help speed up compile times.
As I mentioned in the comment, you could perhaps define the currentImageIndex
variable inside the .m file, however, it would be a static variable that is common to, and shared, by all instances of the class. This can be useful in some situations, but create issues in others. For example, imagine we have 2 slideshow controllers, each with different images created and showing slides in 2 different windows. If they were modifying a shared currentImageIndex
variable, they'd mess each other up if you would switch between them and start clicking Previous and Next indiscriminately. That's why in this case it might make more sense to just make it an instance variable by defining it other your other instance variables in the .h file.
[EDIT] Regarding the :(id)sender
parameter: in this example, it wasn't used at all, I generally do it out of habit, since in some circumstances, it can save a lot of code, and simplify things dramatically. For example, say you had 9 different buttons and you wanted each button to load a specific image (or perform a specific operation). Now, you could define 9 separate methods like - (IBAction)button1Clicked;
, or you could do it the easy way and just define a single - (IBAction)loadImage:(id)sender
method. In your nib file, you would give each button a different tag (an NSInteger
value), like 1 − 9. Then in your single method you could do this:
- (IBAction)loadImage:(id)sender {
NSInteger buttonTag = [(NSButton *)sender tag];
[imageView setImage:[UIImage imageNamed:
[NSString stringWithFormat:@"image%ld.png",buttonTag]]];
}
In this case, sender
is the object that sends the message, which would be the button that was clicked on. Though admittedly a contrived example, by providing that one additional parameter, I probably saved 100 lines of needless code and complexity of having 9 separate methods.
[EDIT #2] Replaced the one pseudo-coded (written in Safari) next:
method with actual code from one of my apps that I know works.
Hope this helps...
you need to declare the currentindex in the header like so:
NSInteger currentImage;
This way the value is saved throughout the views lifetime
精彩评论