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

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]
}
}

Related

Detect a pan over multiple objects?

So here I have a loop that creates a bunch of different squares on the screen, using an array, and I've added a gesture recognizer to detect for a pan. The thing is, I want to be able to smoothly slide over one object to the next, without lifting my finger. But, with my current code I have to lift my finger and slide over each object individually. Does anyone know how to make it so that I can smoothly slide my finger over each object, and have them perform their functions when they've been slid over? Here's my code:
int numby = [squareLocations count];
for (int i = 0; i < numby; i++)
{
NSValue *pointLocation = [squareLocations objectAtIndex:i];
CGPoint tmpPoint = [pointLocation CGPointValue];
UIImage *theSquare = [UIImage imageNamed:#"square.png"];
UIButton *squareButton = [[UIButton alloc] init];
squareButton = [UIButton buttonWithType:UIButtonTypeCustom];
squareButton.frame = CGRectMake(tmpPoint.x, tmpPoint.y, theSquare.size.width, theSquare.size.height);
squareButton.tag = *(&i);
[squareButton setImage:theSquare forState:UIControlStateNormal];
UIPanGestureRecognizer *slide = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(handlePan:)];
[squareButton addGestureRecognizer:slide];
[whereStuffActuallyHappens addSubview:squareButton];
}
}
- (void) handlePan:(UIPanGestureRecognizer *)slide {
[slide setTranslation:CGPointZero inView:slide.view];
NSInteger tag = slide.view.tag;
NSLog(#"Tag is: %i", tag);
[slide.view removeFromSuperview];
}
A kinda hack-ish way to do this would be to add the pan gesture to the superview of your squares instead, and check which one has the location of the gesture colliding with its frame.

iOS Code Displays White Field Rather Than Image Series

The code below is supposed to display a series of images in an infinite, connected loop. Instead, it just displays a totally white field. Thanks to Aaron Hayman for getting me this far.
- (void)layoutScrollImages
{
//Arrangement
NSArray *imageViews = [NSArray arrayWithObjects:#"image1.png", #"image2.png", #"image3.png", nil];
CGRect cRect = scrollView1.bounds;
UIImageView *cView;
for (int i = 0; i < imageViews.count; i++)
{
cView = [imageViews objectAtIndex:i];
cView.frame = cRect;
[scrollView1 addSubview:cView];
cRect.origin.x += cRect.size.width;
}
scrollView1.contentSize = CGSizeMake(cRect.origin.x, scrollView1.bounds.size.height);
scrollView1.contentOffset = CGPointMake(scrollView1.bounds.size.width, 0); //should be the center page in a 3 page setup
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
scrollView1.contentOffset = CGPointMake(scrollView.bounds.size.width, 0);
}
FOLLOW UP:
Nothing I'm doing is making any difference. Currently, my code looks like this, but I'm changing everything I can think of to no avail.
- (void)layoutScrollImages
{
//Horizontal arrangement
NSObject *image1 = #"image1.png";
NSObject *image2 = #"image2.png";
NSObject *image3 = #"image3.png";
NSArray *imageViews = [NSArray arrayWithObjects:image1, image2, image3, nil];
CGRect cRect = scrollView1.bounds;
UIImageView *cView;
for (int i = 0; i < imageViews.count; i++)
{
cView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:[imageViews objectAtIndex:i]]];
cView.frame = cRect;
[scrollView1 addSubview:cView];
cRect.origin.x += cRect.size.width;
}
scrollView1.contentSize = CGSizeMake(cRect.origin.x, scrollView1.bounds.size.height);
scrollView1.contentOffset = CGPointMake(scrollView1.bounds.size.width, 0); //should be the center page in a 3 page setup
[self layoutScrollImages];
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
scrollView1.contentOffset = CGPointMake(scrollView.bounds.size.width, 0);
}
You never initiate a UIImageView. You want to do something like this:
NSArray *imageViews = [NSArray arrayWithObjects:#"image1.png", #"image2.png", #"image3.png", nil];
CGRect cRect;
UIImageView *cView;
for (int i = 0; i < imageViews.count; i++)
{
cView = [[UIImageView alloc] initWithImage:[UIImage imageName:[imageViews objectAtIndex:i]]];
cRect = cView.frame;
cRect.origin.x += scrollView1.frame.size.width;
cView.frame = cRect;
[scrollView1 addSubview:cView];
NSLog(#"imageView bounds: %#", NSStringFromCGRect(cView.frame));
}
Edit:
Try the above and see if anything shows up. Here are some thoughts:
Are you sure that you aren't setting the imageView to have 0 height/width? I threw in an NSLog statement to the loop. It will print the frame of the imageView.
Have you tried adding the images to self.view instead of scrollView1? That would be a good way to make sure that the problem doesn't have to do with the frame of scrollView1. Or use the following:
NSLog(#"imageView bounds: %#", NSStringFromCGRect(scrollView1.frame));

changing between multiple images for an UIImage in xcode

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];

Custom UIImageVIew with touchesEnded works only with the first view

Sorry for bad title :(
I've a controller that has a scrollview where I display some other views, in this case an IngredientImage, that is a subclass of uiimageview:
#import "IngredientImage.h"
#implementation IngredientImage
- (id) initWithImage:(UIImage *)image {
if (self = [super initWithImage:image]) {
}
[self setUserInteractionEnabled:YES];
return self;
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
CGPoint location = [[touches anyObject] locationInView:self];
if (CGRectContainsPoint([self frame], location)) {
NSLog(#"This works...");
}
}
- (void)dealloc {
[super dealloc];
}
#end
and there is the code that puts the views in the scrollview
- (void)viewDidLoad {
[super viewDidLoad];
[self addIngredients];
}
- (void)addIngredients {
NSUInteger i;
for (i = 1; i <= 10; i++) {
UIImage *image = [UIImage imageNamed:#"ing.png"];
IngredientImage *imageView = [[IngredientImage alloc] initWithImage:image];
// 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 = 50;
rect.size.width = 50;
imageView.frame = rect;
imageView.tag = i; // tag our images for later use when we place them in serial fashion
[ingredientsView addSubview:imageView];
[imageView release];
[image release];
}
UIImageView *view = nil;
NSArray *subviews = [ingredientsView subviews];
// reposition all image subviews in a horizontal serial fashion
CGFloat curYLoc = INGREDIENT_PADDING;
for (view in subviews) {
if ([view isKindOfClass:[IngredientImage class]] && view.tag > 0) {
CGRect frame = view.frame;
frame.origin = CGPointMake(INGREDIENT_PADDING, curYLoc);
view.frame = frame;
curYLoc += (INGREDIENT_PADDING + INGREDIENT_HEIGHT);
}
}
// set the content size so it can be scrollable
[ingredientsView setContentSize:CGSizeMake([ingredientsView bounds].size.width, (10 * (INGREDIENT_PADDING + INGREDIENT_HEIGHT)))];
}
the problem is that only the first view handles the touch event, and I don't know why :(
Can you help me?
Thanks
When you call
CGPoint location = [[touches anyObject] locationInView:self];
you are setting location with respect to the bounds of your imageView. But then in your if statement,
if (CGRectContainsPoint([self frame], location))
you are asking if the location is within your frame. But frame and bounds are different. Frame gives coordinates relative to your superview; bounds gives it relative to the view itself.
To fix this, change your if statement to read
if (CGRectContainsPoint([self bounds], location))
Now you are consistently using the same coordinate system in both calls, and your problem should go away.

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.