changing between multiple images for an UIImage in xcode - iphone

been working on an app and have been studying the questions available here but no luck in finding something similar to resolve my problem.
I have an array setup with 4 images and I'm trying to change to a different image every time the image is touched in sequence and then back to first after last image displayed.
For example: image1 "touch" => image2 "touch" => image3 "touch" image4 "touch" => image1.....
The image won't change unless "touched".
My array is setup as:
-(void) viewDidLoad {
imageArray = [[NSArray alloc] initWithObjects:
[UIImage imageNamed:#"image1.png"],
[UIImage imageNamed:#"image2.png"],
[UIImage imageNamed:#"image3.png"],
[UIImage imageNamed:#"image4.png"],
nil];
I then display the first image with the following:
imageView.image = [imageArray objectAtIndex:0];
Then, I'm able to successfully change between two images with the following code:
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [[event allTouches] anyObject];
NSLog(#"'Touches Began");
if ([touch view] == imageView) {
imageView.image = [imageArray objectAtIndex:1];
NSLog(#"Image touched and changed");
}
Now, because I want imageView display more than two changes, I tried to use if statement inside a for loop with no luck:
int touchCount = 0;
for (touchCount = 1; touchCount < 4; touchCount++) {
if ((touchCount < 4) && ([touch view] == imageView)) {
imageView.image = [imageArray objectAtIndex:touchCount];
NSLog(#"Touch Count = %d", touchCount);
}
}
When ran, the debugger shows "Touch Count = 0" and then just crash and exits back into the home screen. Can anybody please help on this problem? Is my concept wrong?

Have an integer as an instance variable which stores which image is being displayed. Set this to 0 on viewDidLoad.
When a touch is registered on the image view, increment the integer. If the value equals the count of your image array, set it back to 0.
Set the image to the element of your image array indicated by the integer value:
// touch registered on image
currentImage++;
if (currentImage == [imageArray count])
currentImage = 0;
imageView.image = [imageArray objectAtIndex:currentImage];

Related

iOS CGRectIntersectsRect with multiple instances of UIImageView?

I have a layout for an application that needs to detect when an image collides with another image.
Here, the user creates multiple 'balls', the same instance of a UIImageView named 'imgView', on the screen by tapping the location they desire:
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *myTouch = [[event allTouches] anyObject];
imgView = [[UIImageView alloc] initWithFrame:CGRectMake(40, 40, 40, 40)];
imgView.image = [UIImage imageNamed:#"ball.png"];
[self.view addSubview:imgView];
imgView.center = [myTouch locationInView:self.view];
}
(imgView is declared as a UIImageView in the header) :
UIImageView *imgView;
Now, I also have an image called 'staff'. It is a long bar that pans horizontally across the screen. I want the image 'staff' to detect EVERY collision it has with the variable 'imgView', or the balls the user has placed on the screen.
Therefore, the user could tap 10 different places on the screen and and 'staff' should be able to catch every single one.
I use this CGRectIntersectsRect code thats activated by an NSTimer:
-(void)checkCollision {
if( CGRectIntersectsRect(staff.frame,imgView.frame)) {
[self playSound];
}
}
However, the intersection is only detected with the LAST instance, or 'ball' the user created. The staff reacts to that one, but pans over the rest. Any help to fix my code to detect all instances would be greatly appreciated.
Each time you create a new ball, you are overriding your imgView instance variable. Thus, your checkCollision method only sees the latest value of imgView, namely the last ball created.
Instead, you could keep track of every ball on screen in an NSArray, then check for collisions against every element in that array. To do that, replace your imgView instance variable with, say:
NSMutableArray *imgViews
Then, sometime early on, say in viewDidLoad initialize the array:
imgViews = [[NSMutableArray alloc] init]
In -touchesEnded:withEvent: add the new UIImageView to the array:
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *myTouch = [[event allTouches] anyObject];
UIImageView *imgView = [[UIImageView alloc] initWithFrame:CGRectMake(40, 40, 40, 40)];
imgView.image = [UIImage imageNamed:#"ball.png"];
[self.view addSubview:imgView];
imgView.center = [myTouch locationInView:self.view];
[imgViews addObject:imgView]
}
And finally, in checkCollision iterate through your array and perform your check on every element
- (void)checkCollision {
for (UIImageView *imgView in imgViews) {
if( CGRectIntersectsRect(staff.frame,imgView.frame)) {
[self playSound];
}
}

Drag elements UIImageView. Using a NSMutableArray

.m
self.elements=[myElements getElements];
imagesElements = [[NSMutableArray alloc]init];
for(ElemetsList *item in self.elements)
{
UIImageView *oneelement = [[UIImageView alloc] initWithImage:[UIImage imageNamed:item.imgElement]];
oneelement.frame = CGRectMake(item.positionX, item.positionY, item.width, item.height);
oneelement.userInteractionEnabled=YES;
[imagesElements addObject:oneelement];
}
for(UIImageView *img in imagesElements)
[self.view addSubview:img];
Then I try to interact with the elements:
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [[event allTouches] anyObject];
for(UIImageView *img in imagesElements)
{
if([self view] == img)
{
CGPoint location = [touch locationInView:self.view];
img.center=location;
}
}
}
But "if ([self view] == img)" is always "NO". Therefore, the elements do not drag.
How to drag and drop items if they are in the array?
When you add your image views, you make them subviews of self.view, therefore you need to test whether img is in the subviews array. It can't be equal to the view that contains it.

Adding UIImageView Objects in UIView to NSMutableArray

I believe I may be dealing with some view issues which are not allowing me to detect and add UIImageView objects to an array. I could really use some suggestions.
I've got a number of UIImageViews with images linked to a UIView that sits on top of a UIViewController (the UIView was added to help with drawRect and some additional advantages). So, when I touch an image and 'drag and drop' it, I want to add that image to an array upon being dropped.
My touchesBegan gets the location of the touch and checks UIImageView is being touched and then centers on that view as follows:
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [[event allTouches] anyObject];
CGPoint location = [touch locationInView:self]; //can't use self.view in a UIView, this may be causing issues?
startLocation = location; // for reference as needed
NSLog(#"Image x coord: %f", location.x);
NSLog(#"Image y coord: %f", location.y);
if ([touch view] == obiWan_Block)
{obiWan_Block.center = location;}
else if ([touch view] == r2d2_Block)
{r2d2_Block.center = location;}
else if ([touch view] == you_Block)
{you_Block.center = location;}
}
Then, I drag the UIImageView around with touchesMoved and finally, 'drop' the image with touchesEnded. When the UIImageView is drop in a certain area of the screen, I 'snap' it to a specific location. It's at this point I want to place this UIImageView into an array, but I'm having no luck. I believe I'm getting confused on the various views being touched and what's getting added via addObject to my NSMutableArray. Or, I could be missing something completely. Here's my touchedEnded method:
-(void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [[event allTouches] anyObject];
CGPoint location = [touch locationInView:self];
UIView *temp = [touch view];
UIImageView *currentImageView = (UIImageView *)[touch view]; //DON'T THINK THIS IS RIGHT
NSLog(#"Current Image View is: %#", currentImageView);
if ((location.x > dropZone.origin.x) && (location.y >= dropZone.origin.y) && ([touch view] != NULL))
{
CGRect frame = temp.frame;
if (touchCount == 0) {
frame.origin.x = 15;
frame.origin.y = 180;
temp.frame = frame;
[quoteArray addObject: currentImageView];
touchCount++;
}
else if (touchCount == 1) {
frame.origin.x = 70;
frame.origin.y = 180;
temp.frame = frame;
[quoteArray addObject: currentImageView];
touchCount++;
}
....
I have an NSLog statement to check if addObject is working as follows:
NSLog(#"the quote array contains %d items. Contents = %#",[quoteArray count], quoteArray);
The log always says:
the quote array contains 0 items. Contents = (null)
Please advise and thanks!
Your last part of code shows that you have uninitialized quoteArray. Check code when you create it, I guess you missed something in your init method. Because if array was correct then NSLog should show below:
NSArray *quoteArray = [NSArray array];
NSLog(#"%#", quoteArray);
2011-11-17 17:37:00.506 TestApp[1382:207] ( )

Trying to reuse variable to avoid abandoned memory

I've got a TapDetectingImageView class that is pertaining in memory after usage because I do not reuse it in my code.
I change my code now to reuse it instead of re creating a new one each time.
The goal is to configure that TapDetectingImageView object and put it in a view. I'll do it 8 times but with the code below, only the last one is showing. I'm sure I'm missing something, but what? ;)
The view holding the imageViews is potatoeView. I'm adding new TapDetectingImageView through:
[potatoeView addSubview:imageView];
What's wrong in that code?
for (int i = 0; i <= numberOfPotatoes-1; i++)
{
NSLog(#"potatoesView Generation : %d",i);
NSArray *imgArray = [[NSArray alloc] initWithArray:[p objectAtIndex:i]];
UIImage *img1 = (UIImage *) [imgArray objectAtIndex:0];
UIImage *img2 = (UIImage *) [imgArray objectAtIndex:1];
NSString *imgName = (NSString *) [imgArray objectAtIndex:2];
if (imageView == nil) {
imageView = [[TapDetectingImageView alloc] initWithImage:img1 imageHighlighted:img2];
}else {
[imageView setImage:(UIImage *)img1];
[imageView setImageHighlighted:(UIImage *)img2];
}
[imageView setDelegate:self];
// setup each frame to a default height and width, it will be properly placed when we call "updateScrollList"
CGRect rect = imageView.frame;
rect.size.height = [potatoesSize floatValue] ;
rect.size.width = [potatoesSize floatValue] ;
imageView.frame = rect;
[imageView setName:(NSString *)imgName];
imageView.tag = i+1; // tag our images for later use when we place them in serial fashion
NSValue *val = [potatoesSizeAndPositions objectAtIndex:i];
CGPoint point = [val CGPointValue];
imageView.center = point;
[potatoeView addSubview:imageView];
[imgArray release];
}
You seem to be fundamentally misunderstanding how your views are drawn. When you set up the same view instance with eight different positions and images, it doesn't "stamp" them all out on some canvas as it goes. Its state won't be queried until the main run loop gets around to drawing your view, at which point it'll ask your view for its frame and contents and so on to draw it. If you want to draw eight different images with UIViews, you'll need eight different views.
You only ever create one view, set it as the subview and then change it n-1 times. Drop the if (imageView==nil) and create all 8 of them.

adding image to array at runtime and clear it on button click

wat i am trying to is, each time user touches screen, i am adding a small bulletr image on screen
UIImage *img = [UIImage imageNamed:#"shoot_a.png"]; //bullet shot image
im.image = img;
[self.view addSubview:im];
, if user touches 50 times, there will be 50 images on screen.
now i want, if user hit a button, all these bullet should be remove from the screen.
i hope i am clear about my question.
[im removefromsuperview] doesnt work for me.
if i want to add images to array at run time, how can i add and release?
or is there any better way to clear all images
regards.
this is my touch method, i m adding bullet images on screen frm heere,, but these images are not getting added in Array
// Touch method
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
if(restrictTap == YES){
NSUInteger numTaps = [[touches anyObject] tapCount];
NSString *numTapsMessage = [[NSString alloc] initWithFormat:#"%i", numTaps];
[numTapsMessage release];
// getting location
CGPoint touchLocation = [[touches anyObject] locationInView:self.view];
NSString *locationMessage = [[NSString alloc] initWithFormat:#"Location: X = %.0f Y = %.0f", touchLocation.x, touchLocation.y];
//bullet shot image
im = [[UIImageView alloc] initWithFrame:CGRectMake(self.location.x, self.location.y, 12.0, 12.0)];
float j =self.location.x;
float i =self.location.y;
img = [UIImage imageNamed:#"shoot_a.png"]; //bullet shot image
im.image = img;
//im.hidden = NO;
[self.view addSubview:im]; ///bullet shot image is over transparent view
[imageArray addObject:img];
}
}
You could keep track of them via a NSMutableArray property and use that to remove them:
// create e.g. in initializer:
imageArray = [[NSMutableArray alloc] init];
// clean-up, e.g. in dealloc:
self.imageArray = nil;
// add image:
[imageArray addObject:im];
// remove all:
for (UIView *img in imageArray) {
[img removeFromSuperview];
}
[imageArray removeAllObjects];
You can set a particular tag to all the bullet imageViews when you add it to your view
im.tag = 1000;
and then on button touch, you can iterate through subviews array of your view and remove all views with that tag. something like :
int count = [[self.view subviews] count];
for(int i = 0; i < count; i++)
{
if([(UIView*)[[self.view subviews] objectAtIndex:i] tag] == 1000)
{
[(UIView*)[[self.view subviews] objectAtIndex:i] removeFromSuperview]
}
}