small medium large xlarge

Generic-user-small
22 Sep 2009, 12:56
Daniel Bull (5 posts)

I am having a problem with basic Animations, stuff at the very beginning of Bill Dudney’s book, but I thought maybe I could get some advice here anyway. This is my first post to a Pragmatic Bookshelf forum, so I hope I got the formatting correct. There doesn’t seem to be a “preview post” option.

I have an app in which I want to show a UIImageView repeatedly, but first changing the image property of the UIImageView before each showing. When a given instance of the UIImageView is showing, the user is supposed to be able to touch the screen and cause the image to zoom out. If instead the user clicks on a button elsewhere on the screen, a graphic is shown briefly over the button by using the Touch Down event of the button and then basic animations are triggered by the Touch Up Inside event. This is supposed to fade in a graphic and then fade the graphic back out. These first two animations are then followed by another fade in and fade out.

The way I have set this all up works perfectly in Simulator 3.1. When I try the same code in my iPod with OS 3.1.1 it works for two iterations, then for the third iteration Touches no longer function, and when the button is touched, the Touch Down graphic doesn’t appear, and the first two animations are skipped.

I would be happy to post as much code as necessary to clarify all this, but I’m not sure what is needed.

Here’s the Touches routine:

// Shows the "Tap" graphic when user touches the game screen
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
	if (guessButton.enabled == YES)
	{
		UITouch *touch = [[event allTouches] anyObject];
		if (CGRectContainsPoint(gameRect, [touch locationInView:nil])) { // Must touch graphic of Imp or Oaf
			CGPoint pt = [[touches anyObject] locationInView:nil];
			pt.y -= 12.0;	// Adjust position so center of ring on graphic shows where touch was made
			pt.x += 2.0;
			tap_small.center = pt;
			[tap_small setAlpha:0.0];
			[UIView beginAnimations:nil context:NULL];
			[UIView setAnimationDelay:0.1];
			[UIView setAnimationDuration:0.25];
			[UIView setAnimationDelegate:self];
			[UIView setAnimationDidStopSelector:@selector(fadeTapSmall:finished:context:)];
			[tap_small setAlpha:1.0];
			[UIView commitAnimations];
		}
	}
}	

// Fade out the "Tap" graphic
-(void)fadeTapSmall:(NSString*)animationID finished:(BOOL *)finished context:(void*)context {
	[UIView beginAnimations:nil context:NULL];
	[UIView setAnimationDuration:0.25];
	[UIView setAnimationDelegate:self];
	[UIView setAnimationDidStopSelector:@selector(doIncreasePicture:finished:context:)];
	[tap_small setAlpha:0.0];
	[UIView commitAnimations];
}	

-(void)doIncreasePicture:(NSString*)animationID finished:(BOOL *)finished context:(void*)context
{
	[self increasePicture];
}

I use:

[pictureView setImage:[UIImage imageNamed:[NSString stringWithFormat:@"%s",creatures[creatureChosen]]]];

to set the image. The fade-ins and fade-outs are:

-(IBAction) imageChosen {
	[[[IorOAVAudio sharedInstance] player2] stop];
	[self showWholePicture];	// Show the full picture
	guessButton.enabled = NO; 
	buttonOn.hidden = YES;
	straightZeros = 0;
	if (creatureChosen < 30) {	// Image was correctly guessed
			[[IorOAVAudio sharedInstance] makeImageAudioServiceFileID];
			[UIView beginAnimations:nil context:NULL];
			[UIView setAnimationDelay:0.5];
			[UIView setAnimationDuration:0.5];
			[UIView setAnimationDelegate:self];
			[UIView setAnimationDidStopSelector:@selector(playWinSound:finished:context:)];
			[message_box_yes setAlpha:0.95];
			[UIView commitAnimations];
	} else {
		straightImages = 0;
		[[IorOAVAudio sharedInstance] makeImageAudioServiceFileID];
		[UIView beginAnimations:nil context:NULL];
		[UIView setAnimationDelay:0.5];
		[UIView setAnimationDuration:0.5];
		[UIView setAnimationDelegate:self];
		[UIView setAnimationDidStopSelector:@selector(playLoseSound:finished:context:)];
		[message_box_no setAlpha:0.95];
		[UIView commitAnimations];
	}
}	

-(void)playWinSound:(NSString*)animationID finished:(BOOL *)finished context:(void*)context {
	[[IorOAVAudio sharedInstance] makeWinAudioServiceFileID];
	[UIView beginAnimations:nil context:NULL];
	[UIView setAnimationDelay:1.5];
	[UIView setAnimationDuration:0.75];
	[UIView setAnimationDelegate:self];
	[UIView setAnimationDidStopSelector:@selector(checkLuckyDuck:finished:context:)];
	message_box_yes.hidden = NO;
	[message_box_yes setAlpha:0.0];
	[UIView commitAnimations];
}

-(void)playLoseSound:(NSString*)animationID finished:(BOOL *)finished context:(void*)context {
	[[IorOAVAudio sharedInstance] makeLoseAudioServiceFileID];
	[UIView beginAnimations:nil context:NULL];
	[UIView setAnimationDelay:1.5];
	[UIView setAnimationDuration:0.75];
	[UIView setAnimationDelegate:self];
	[UIView setAnimationDidStopSelector:@selector(showLose:finished:context:)];
	message_box_no.hidden = NO;
	[message_box_no setAlpha:0.0];
	[UIView commitAnimations];
}

-(void)showWin:(NSString*)animationID finished:(BOOL *)finished context:(void*)context {
	gameScore += roundScore;
	numberOfRoundsCorrect++;
	NSString *scoresText = [[NSString alloc] initWithFormat:@"%i", gameScore];
	self.totalScoresLabel.text = scoresText;
	[scoresText release];
	[self.totalScoresLabel setNeedsDisplay];
	[self showRoundNumber];
}

-(void)checkLuckyDuck :(NSString*)animationID finished:(BOOL *)finished context:(void*)context {
	if (++straightImages == 3) {
		gameScore += 50;
		if (luckyDuckBadge == nil) {
			NSString *myDuckImage = [[NSString alloc] initWithFormat:@"lucky_duck_PONGED.png"];
			UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:myDuckImage]];
			luckyDuckBadge = imageView;
			luckyDuckBadge.frame = CGRectMake( 70.0, 70.0, 185.0, 219.0 );
			[self.view addSubview:luckyDuckBadge];
			[self.view setNeedsDisplay];
			[imageView release];
			imageView = nil;
			[myDuckImage release];
			myDuckImage = nil;
		}	
		[luckyDuckBadge setAlpha:0.0];
		luckyDuckBadge.hidden = NO;
		[UIView beginAnimations:nil context:NULL];
		[UIView setAnimationDelay:0.5];
		[UIView setAnimationDuration:1.5];
		[UIView setAnimationDelegate:self];
		[UIView setAnimationDidStopSelector:@selector(fadeLuckyDuck:finished:context:)];
		[luckyDuckBadge setAlpha:1.0];
		[UIView commitAnimations];
		straightImps = 0;
	} else {
		gameScore += roundScore;
		numberOfRoundsCorrect++;
		NSString *scoresText = [[NSString alloc] initWithFormat:@"%i", gameScore];
		self.totalScoresLabel.text = scoresText;
		[scoresText release];
		[self.totalScoresLabel setNeedsDisplay];
		[self showRoundNumber];
	}
}

-(void)fadeLuckyDuck:(NSString*)animationID finished:(BOOL *)finished context:(void*)context {
	[UIView beginAnimations:nil context:NULL];
	[UIView setAnimationDelay:0.5];
	[UIView setAnimationDuration:0.5];
	[UIView setAnimationDelegate:self];
	[UIView setAnimationDidStopSelector:@selector(showWin:finished:context:)];
	[luckyDuckBadge setAlpha:0.0];
	[UIView commitAnimations];
	
}

The thing is, if I repeatedly show:

[pictureView setImage:[UIImage imageNamed:[NSString stringWithFormat:@"image1.jpg"]]];

instead of:

[pictureView setImage:[UIImage imageNamed:[NSString stringWithFormat:@"%s",creatures[creatureChosen]]]];

the problem goes away. Unfortunately, the essence of the game rests on the change of image from round to round.

I’m totally flummoxed. I’ve changed the names of some of the routines and so on to protect the innocent, so there may be one or two minor typos, but I think not.

Thanks for any help, that’s for sure.

Biopic_100x100_pragsmall
22 Sep 2009, 13:19
Bill Dudney (917 posts)

Hi Daniel,

I would put the images into an array instead of loading them with imageNamed: each time. That method builds a cache but you have very little control over it.

Give the note at the bottom of your post that showing the same image over and over again works fine, but using the array of C strings goes south I would make sure your array has what you expect in it.

Moving to an NSArray of images would solve both problems I think.

Good luck!

Generic-user-small
22 Sep 2009, 16:29
Daniel Bull (5 posts)

Hi Bill

I’m enjoying your book.

I have tried this:

-(void) createNameList {
	//Create an array to hold names of creatures
	nameList = [NSMutableArray arrayWithObjects:
				@"image1.jpg", @"image2.jpg", @"image3.jpg", @"image4.jpg", @"image5.jpg",
				@"image6.jpg", @"image7.jpg", @"image8.jpg", @"image9.jpg", @"image10.jpg",
				@"image11.jpg", @"image12.jpg", @"image13.jpg", @"image14.jpg", @"image15.jpg",
				@"image16.jpg", @"image17.jpg", @"image18.jpg", @"image19.jpg", @"image20.jpg",
				@"image21.jpg", @"image22.jpg", @"image23.jpg", @"image24.jpg", @"image25.jpg",
				@"image26.jpg", @"image27.jpg", @"image28.jpg", @"image29.jpg", @"image30.jpg",
				@"altimage1.jpg", @"altimage2.jpg", @"altimage3.jpg", @"altimage4.jpg", @"altimage5.jpg",
				@"altimage6.jpg", @"altimage7.jpg", @"altimage8.jpg", @"altimage9.jpg", @"altimage10.jpg",
				@"altimage11.jpg", @"altimage12.jpg", @"altimage13.jpg", @"altimage14.jpg", @"altimage15.jpg",
				@"altimage16.jpg", @"altimage17.jpg", @"altimage18.jpg", @"altimage19.jpg", @"altimage20.jpg",
				@"altimage21.jpg", @"altimage22.jpg", @"altimage23.jpg", @"altimage24.jpg", @"altimage25.jpg",
				@"altimage26.jpg", @"altimage27.jpg", @"altimage28.jpg", @"altimage29.jpg", @"altimage30.jpg",
				nil ];
	[nameList retain];
        // See what's actually in the array
	//	int i;
	//	for (i = 0; i < 59; ++i)
	//		NSLog (@"%@", [nameList objectAtIndex:i]);
}

-(NSString *)getNameFromList {
	return [nameList objectAtIndex:creatureChosen];
}

But I got more or less the same result. I have tried both NSArray and NSMutableArray. Maybe this is not what you were suggesting at all. I have also tried using imageNamed and that was no better. In any event, the app doesn’t crash in the usual sense. Eventually, it gets caught up in an infinite loop (but not always at the same place, it seems). Once it simply kept looping through the Touches Began routine, even though no Touches had been made. After some number of trips through whatever loop it is stuck in, the app will exit, but no crash report shows up in the Organizer. Everything works fine in the Simulator, but that is running Intel instructions, and the iPod is of course an Arm6 machine so it’s no surprise that the Simulator doesn’t simulate perfectly. NSZombie always reports that there is something wrong with a -CALayer, but I don’t know how to interpret the number reported, that is, I can’t relate a program location with the address given, except by inspecting the memory, and I don’t know Arm machine code. If it were a Freescale 8 or 16 bit chip, that would be different.

This problem has been vexing me for some time. Do you have any knowledge as to what the chances are that I would get good results by using one of my Apple Developer tech support tickets? Also, is it worth trying Affine transformations?

Thanks, Dan

Biopic_100x100_pragsmall
22 Sep 2009, 17:37
Bill Dudney (917 posts)

Hi Dan,

I was thinking of you making an array of the image objects, not the names.

From the sounds of it you have a bug in your logic, not in the animation or orhter stuff.

I would simplify the code down until you have the bare minimum (like 2 images or other simplification) that shows the bug. Then fix that and the rest will likely work.

If you are new to debugging you might find this book helpful

http://pragprog.com/titles/pbdp/debug-it

Good luck!

Generic-user-small
22 Sep 2009, 20:24
Daniel Bull (5 posts)

Hi Bill -

I’m not new to debugging, but I’m new to object oriented coding. I have several decades of experience with C, especially for Freescale (Motorola) 8 and 16 bit chips. I am also fairly competent at designing the boards for these CPUs, and a couple of them have been used in laboratory equipment and in real time control. But this stuff is another breed of animal. I think I’m doing OK with Objective-C at this point, although I make many mistakes.

Does the debug book you mentioned deal with the gdb debugger used by Apple? The manual for the gdb debugger runs to about 500 pages or so. I’ll buy the book if you really think it will help me.

At my age (70) I’m probably insane to be starting a new career writing apps for the iPhone, but it gives me a chance to work with my son-in-law, who is a very creative artist with fifteen years of experience designing games and such.

Thanks for your time. I really appreciate it.

Dan

Biopic_100x100_pragsmall
22 Sep 2009, 23:20
Bill Dudney (917 posts)

Hi Dan,

Man that is fantastic that you are going off in a new direction! Its not crazy or insane, its fantastic! You never get old if you are learning new stuff :)

The book does not help with GDB but it will help you think about debugging from more of an OO perspective.

The reason I suggest it was because of the amount of code you posted. Its too much to figure out the problem and it seems like you were ‘grasping at straws’. As you know it is really hard to fix bugs when you are in that mode. Please don’t take this the wrong way, I understand how steep the curve is to get up to speed with this stuff.

I’m not sure about the book helping, with as much exp as you have debugging really hard stuff its probably old hat. Might be helpful to look at the excerpts.

I’m sure that the problem is something is not setup as you think it is. I would either put some breakpoints in your code so you can see what the real images are before putting them into the view or put some log messages (with NSLog) to verify that what you think is there really is there.

Good luck!

Generic-user-small
24 Sep 2009, 17:55
Daniel Bull (5 posts)

Hi Bill,

I know your time is valuable, but I thought this might interest you. At first, I said to myself that I already had quite a bit of experience debugging. Then I reconsidered, and thought “Man, that’s really arrogant!” So I bought the “Debug-It!” book as a combo. I put the eBook on my iPod (where your Core Animation eBook also resides) and went to the local Starbuck’s to read it. I read through the first pages until I got to the part about logging. Still arrogant, I told myself that I was already using a lot of NSLog calls trying to solve my problem.

Then I came to the part where Mr. Butcher discusses how many use logging in a very haphazard way (or words to that effect.) It suddenly dawned on me that I was doing that very thing, not thinking clearly and systematically about how I was logging. It took me about two minutes to come up with a better scheme of logging.

I went home, fired up Xcode, and put in NSLogs in three places I had not used before, even though logic had been screaming at me to do so. In ten minutes I had solved a problem I had been flogging for a couple of weeks. For the record, I was releasing objects then trying to modify them, which I had already deduced was probably my bug (NSZombie had told me that), but I had not thought systematically about where the release might be happening. It was happening when I got a low memory notification. Of course, the Simulator would never report this, but the device did. Here I thought I was following Apple’s recommendations by setting up an NSNotification then releasing objects when the low memory notification occurred. So I fixed that, and so far the problem has not reappeared. Thus far, the low memory situation has not caused the app to crash or hang up on the device. Time will tell.

I tell you all this because you gave me such good advice that I wanted you to know first how grateful I am, and secondly, to confirm that the Power of Lateral Thinking is considerable, which is basically what you told me in your last post.

Once again, thank you very much for taking the time to advise me.

Dan

Biopic_100x100_pragsmall
24 Sep 2009, 21:17
Bill Dudney (917 posts)

Hey Dan,

Glad you got it working! Congrats.

And you are most welcome. Make sure to post back when you ship your app!

You must be logged in to comment