Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community!
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trial
Kian Woo
3,097 PointsAnimate This - Extra Credit - motionBegan event
Hi, I'm trying to do the Animate This - Extra Credit task for the crystalball app. I managed to animate the predictionLabel from the bottom of the screen upwards, but was not able to animate the predictionLabel down to the bottom of the screen during the motionBegan event. I debugged to check that is the code is being run, and it is, but nothing appears to happen on the simulator. When I don't call the makePrediction method in the motionEnded function, the motionBegan code works and the label moves down! (I tapped to get a prediction, then sent a shake gesture to move it down...)
Any ideas?
Here is the code:
- (void) makePrediction {
NSUInteger index = arc4random_uniform(self.predictionArray.count);
self.predictionLabel.text = [self.predictionArray objectAtIndex:index];
[self.imageView startAnimating];
self.predictionLabel.frame = CGRectMake(20, 488, 280, 42); // move label to bottom of screen
[UIView animateWithDuration:2.0 animations:^{
self.predictionLabel.frame = CGRectMake(20, 205,280, 42); // animate it upwards
}];
}
- (void) motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event {
NSLog(@"motionBegan");
self.predictionLabel.text = @"is anything happening?";
if ( motion == UIEventSubtypeMotionShake ){
[UIView animateWithDuration:2.0 animations:^{
self.predictionLabel.frame = CGRectMake(20, 488,280, 42); // animate it downwards
}];
}
}
- (void) motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event {
NSLog(@"motionEnded");
if ( motion == UIEventSubtypeMotionShake ){
[self makePrediction];
}
}
- (void) motionCancelled:(UIEventSubtype)motion withEvent:(UIEvent *)event {
NSLog(@"motion cancelled");
}
- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
NSLog(@"touchesBegan");
}
- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
NSLog(@"touchesEnded");
UITouch *touch = [touches anyObject];
if ([touch tapCount] == 1) {
[self makePrediction];
} else if ([touch tapCount] ==2 ) {
self.predictionLabel.text = @"";
}
}
- (void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
NSLog(@"touchesMoved");
}
2 Answers

Amit Bijlani
Treehouse Guest TeacherThe problem is that motionBegan
and motionEnded
events happen too quickly that the first animation never gets a chance to finish. If you want to see the label go down and then come back up then you can add the following code to the motionEnded
method:
- (void) motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event {
if ( motion == UIEventSubtypeMotionShake ){
[UIView animateWithDuration:1.0 animations:^{
self.predictionLabel.frame = CGRectMake(20, 488,280, 42); // animate it upwards
} completion:^(BOOL finished) {
[self makePrediction];
}];
}
}

Susan Huffaker
3,546 PointsIs it possible to see the finished code that works? I've had trouble with this, too. Thanks!
Amit Bijlani
Treehouse Guest TeacherAmit Bijlani
Treehouse Guest TeacherI will update the Extra Credit so it's not misleading
Kian Woo
3,097 PointsKian Woo
3,097 PointsThank you! Yes, that's what I was trying to do, and it works now.
Michael Sheaver
2,751 PointsMichael Sheaver
2,751 PointsI am having a similar challenge, but I took a different, simpler approach by putting all of the animations into the makePrediction method, thus avoiding the timing issues encountered with using the motionBegan and motionEnded methods. To my complete surprise, I got the same result as Kian in his original post. All of the NSLogs display in the correct order, but the first animation just does not work. This is (in my mind) very straightforward coding, but obviously I am missing something.
Michael Sheaver
2,751 PointsMichael Sheaver
2,751 PointsI am a newbie here, so how can I paste a block of code and get it to appear normally? In the previous reply, I tried to wrap the code in backticks as explained in the Markdown Basics page, but that did not work either.
Amit Bijlani
Treehouse Guest TeacherAmit Bijlani
Treehouse Guest TeacherAs displayed in my answer above you need to use the method
UIView animateWithDuration:animations:completion:
and put the code to move the label upward in the completion block because it waits for the first animation to finish. In your code both the animation occur so quickly one after the other that you cannot see one complete and the other begin.For code formatting use three backticks followed by the name of the language like this:
Michael Sheaver
2,751 PointsMichael Sheaver
2,751 PointsMany thanks for all your help, Amit; I was finally able get the animations working as intended, and even built in fade-in and fade-out effects using the alpha value.