Friday, October 16, 2009

Carter's Coin Flip Version 1.5 Submitted to the App Store

By Carter:
In the new version my dad and I have put a new toolbar that is easier to use.
We have also chosen two new coins along with the Franc one. We added a Spanish coin with a soccer ball on the tails side of it for soccer fans. We also added a one pound piece from Great Britain, with queen Elizabeth on the heads side.
The new game has also added numerals to the statistics mode, so you now that flip number 1520 was heads and the 40000th was tails
I enjoyed making the new version and I hope that you enjoy using the new version to decide whether to do this or that.

By Dad:
In the original version of CCF we made the transition from the coin view to the statistics view using the “card flipping” motif and a button in the top corner of the screen. However, we discovered that we were mis-using the UI element. People kept expecting that the statistics screen and the coin screen were somehow related. The biggest change in the 1.5 version is to move to a tab bar view to indicate that the two modes are not related.

Thursday, October 1, 2009

Single Tap and Double Tap iPhone

By Dad:
We decided to use a single-tap and double-tab pattern to have Carter’s Coin Flip decide if the user wanted to flip the coin (single tap) or change to a new coin (double tap). Knowing that tapcount was the property of touches that we wanted, the touchesBegan method started out something like this:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{

UITouch *touch = [[event allTouches] anyObject];

if (CGRectContainsPoint(coin.frame,[touch locationInView:self.view])) {

if (touch.tapCount == 2) {

[myCoin changeCoin];

}else{

[myCoin onFlip];

}

}else{

//Code to change the background image since the user

//tapped outside of the coin image.

}


So, the code above WANTS to call the changeCoin method of the myCoin object (the UIImageView holding the picture of the coin) when the user taps twice or call the onFlip method if the user only taps once.


This code almost works.


When the user does a double tap the coin does change, but only after it flips. So, on a double tap, it is clear that the first tap of the double tap is counted as a single tap and then the second tap of a double tap is counted as the double tap. This is not what I was expecting.


A few quick Google searches turned up curious threads on the standard coding discussion boards. Click through if you must, but the themes are the same: this double tap isn’t as straight forward as people expected:

The last board I visited suddenly brought everything into clarity. It is an RTFM question. (IphoneSDK.com Message Thread). I should have known, that Apple would not have expected us to use timers or strange masking of objects or something. They would have laid it out, right in the very first document that all new developers should read through, the iPhone Programming Guide.


In essence, the iPhone Programming Guide says that if you are looking for 2 or 3 or 4 taps you will need to delay the code for the touches below your number. So, at one tap you call a function with a slight delay. If a second tap occurs within your specified timeframe (a few tenths of a second), you cancel the call and initiate a call to the function that handles two touches. This pattern is repeated for 3 and 4 touches etc. So, the current (v 1.5) Carter’s Coin Flip application incorporates this code:


- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{

UITouch *touch = [touches anyObject];

if (touch.tapCount == 2) {

[NSObject cancelPreviousPerformRequestsWithTarget:self];

}

}


- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{

UITouch *touch = [touches anyObject];

if (touch.tapCount == 1) {

if (CGRectContainsPoint(coin.frame,[touch locationInView:self.view])){

[self performSelector:@selector(onFlip) withObject:nil afterDelay:0.3];

}else{

//I change the background image here

}

} else if (touch.tapCount == 2) {

[theCoin changeCoin:coin];

}

}



Notice that I have some code in touchesBegan and the rest in touchesEnded. I think I could have put it all in touchesEnded, and still given the same illusion to the user. However having it in both locations made it easer for me to read the code. I got a little confused by the part of the performSelector command’s withObject requirement. At first I thougth the withObject would be optional given my reading of the documentation. However, the code didn’t work until I added the withObject parameter. I think it has something to do with the fact that the afterDelay parameter is there. In .net coding, any of the optional parameters can be omitted, but it seems that in ObjectiveC you need to list the optional parameters and just pass in nil.