animationDidStop method called immediately - objective-c

I've never had this issue come up before. my animationDidStop method is being called before the animation actually completes. animationDidStart gets called first, but then animationDidStop is called immediately after. I tried to handle this using an animation completion block, but it called the animation completed immediately still. Anybody run across this before? I really could use a bit of help. THANK YOU.
-James
CODE:
-(void) runAnimation {
//Create an animation that rotates the tile
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:#"transform.rotation"];
[animation setDuration:6];
[animation setFromValue:[NSNumber numberWithFloat:0]];
[animation setToValue:[NSNumber numberWithFloat:0.5*M_PI]];
[animation setDelegate:self];
animation.fillMode = kCAFillModeForwards;
animation.removedOnCompletion = NO;
[[self.view viewWithTag:100].layer addAnimation:animation forKey:#"solutionRotate"];
}
-(void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag
{
if (theAnimation == [[self.view viewWithTag:100].layer animationForKey:#"solutionRotate"]){
//test
NSLog (#"test");
}
}

If the layer is not part of any layer tree then the animation will end immediately since there is nothing to actually animate on screen. Make sure the animated view is added to a visible view hierarchy.

Related

Xcode Animations complete instantly - CAAnimations call didStop - flag = FALSE

I'm getting some weird bugs. I thought I had a handle on this. I copied code from one of my other projects. I'm wondering if it could be something to do with my custom class.
I have a view controller initialize my custom class called "TitleCardView"
Inside there I have a bunch of animations like this one:
CGPoint startPointb = borderMaskLayer.position;
CGPoint endPointb = CGPointMake(borderMaskLayer.position.x, borderMaskLayer.position.y-1000);
CABasicAnimation* bmoveAnim = [CABasicAnimation animationWithKeyPath:#"position"];
bmoveAnim.delegate=self;
[bmoveAnim setValue:#"borderMaskAnim1" forKey:#"id"];
bmoveAnim.fromValue = [NSValue valueWithCGPoint:startPointb];
bmoveAnim.toValue = [NSValue valueWithCGPoint:endPointb];
bmoveAnim.duration = 1;
[bmoveAnim setBeginTime:CACurrentMediaTime()+.4];
bmoveAnim.fillMode = kCAFillModeForwards;
bmoveAnim.removedOnCompletion = NO;
bmoveAnim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
[self.borderLayer.mask addAnimation:bmoveAnim forKey:#"position"];
[self.borderWhiteLayer.mask addAnimation:bmoveAnim forKey:#"position"];
The animation works fine but when I try to implement AnimationDidStop{, as soon as the view loads, all the animations get logged by the delegate method with the FALSE (did not finish) flag.
I added a button and tried to use:
[UIView animateWithDuration:6 animations:^{
continueButton.alpha = 1.0f;
}];
and this code with the delay parameter....
Same problem. As soon as the view loads, its like the animation gets run immediately with a duration of 0.
Are you not supposed to add animations in your init method? I feel like there must be a rule I'm breaking that I don't know about.
This code does work:
this button is the last thing in the init method
continueButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[continueButton addTarget:self
action:#selector(titleNext)
forControlEvents:UIControlEventTouchUpInside];
[continueButton setTitle:#"Click to Continue" forState:UIControlStateNormal];
continueButton.frame = CGRectMake(0.0, 390.0, 320.0, 75.0);
[self addSubview:continueButton];
continueButton.alpha = 1.0;
then this is the method it calls
-(void)titleNext{
// proceeds to the motto page from the title page
[UIView animateWithDuration:.6 animations:^{
continueButton.alpha = 0.0f;
}];
}
So can anyone tell me why my animations are acting weird???
I recreated the project and found the animationDidStop delegate worked when the animations were created in -(void)viewDidAppear{ instead of -(void)viewDidLoad{
For swift it works if the animations are in
override func viewDidAppear(_ animated: Bool)

Ios go to next view using a button without using navigation controller

just getting started with IOS - worked out a few tutorials -
Everything i have worked with in the tutorials - i have been using the navigation controller to go to the next view when clicking on a button.
well i was having a look at the logos quiz app by aticoD.
i cant see any navigation controller on this app- it has some custom arrow picture, that acts as a back button- but the navigation bar is not visible.
is it using this method ???-
- (void)viewWillAppear:(BOOL)animated {
[self.navigationController setNavigationBarHidden:YES animated:YES];
}
--- you can see on the app, to choose level - you have to swipe -
can anyone give me a few guidelines on how to implement this part. or link me to a tutorial.
you need to set this code
UIViewController *viewController = [[UIViewController alloc] init];
//Animation
CATransition *animation = [CATransition animation];
[animation setDuration:0.5];
[animation setType:kCATransitionMoveIn];
[animation setSubtype:kCATransitionFromRight];
[animation setFillMode:kCAFillModeForwards];
[animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]];
//animation add to layer.
[[viewController.view layer] addAnimation:animation forKey:#"pushAnimation"];
[[self.navigationViewController.view layer]addAnimation:animation forKey:#"pushAnimation"];
[self.navigationViewController pushViewController:seeAllViewController animated:YES];
for difference kind of animation you just need to change animation Type,subType and fillMode.

How to make an Auto-hidden Toolbar in iPad app?

I'm new to Xcode development and have a (hopefully simple) question:
I want to write an iPad App which shows a document in an UIPageView and in addition shows a bar at the bottom to navigate in the document (i.e. with buttons on it for each chapter).
This bar should automatically hide (except a small grip) while switching pages and show up when pressing (or dragging) the grip.
The bar should overlap the PageView (PageView not resized).
I already finished the PageView (based on the template in XCode) but don't know the best way to implement the bottom-bar.
Any suggestions?
Examples welcome.
to show
[self doSingleViewHideAnimation:myToolBar:kCATransitionFromBottom];
-(void)doSingleViewHideAnimation:(UIView*)incomingView:(NSString*)animType
{
CATransition *animation = [CATransition animation];
[animation setType:kCATransitionPush];
[animation setSubtype:animType];
[animation setDuration:0.5];
[animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
[[incomingView layer] addAnimation:animation forKey:kCATransition];
incomingView.hidden = YES;
}
To hide
[self doSingleViewShowAnimation:myToolBar:kCATransitionFromTop];
-(void)doSingleViewShowAnimation:(UIView*)incomingView:(NSString*)animType
{
CATransition *animation = [CATransition animation];
[animation setType:kCATransitionPush];
[animation setSubtype:animType];
[animation setDuration:0.5];
[animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
[[incomingView layer] addAnimation:animation forKey:kCATransition];
incomingView.hidden = NO;
}
Make a new view.
Put a tap gesture recognizer on it
When it's tapped use UIView animations to slide it in or out.
what i found is and also working for me is as under
first i put one toolbar in xib like this
then create one IBOutlate in .h file like this
#property (retain, nonatomic) IBOutlet UIToolbar *toolbar;
then attach it to the toolbar in xib like this
then i create one UITapGestureRecognizer in .m file as below
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handle_Tap:)];
tap.numberOfTapsRequired = 1;
tap.numberOfTouchesRequired = 1;
[self.view addGestureRecognizer:tap];
and the handle_Tap: method is as follow in .m file for sure
-(void)handle_Tap:(id)sender
{
self.toolbar.hidden = !self.toolbar.hidden;
}
that's all i need to do and the toolbar is appeared when taped and disappeared when tapped again whola!!
It's done thanks to Apple Documents
Happy Codding !!
Enjoy Day :)

Using NSViewAnimation with NSAnimationEaseOut weird behaviour

In one of my views that can be dragged, if the user drops it at an inappropriate place, it simply drops back to the original frame that was recorded when the mouse went down. This has been working fine for a few days with no animation, but I've decided to introduce animation:
-(void)dropToFrameOrigin:(NSPoint)newFrameOrigin animated:(BOOL)animated {
if (animated) {
NSRect newFrameRect = [self frame];
newFrameRect.origin = newFrameOrigin;
NSDictionary *animationInfo = [NSDictionary dictionaryWithObjectsAndKeys:self, NSViewAnimationTargetKey,
[NSValue valueWithRect:[self frame]], NSViewAnimationStartFrameKey,
[NSValue valueWithRect:newFrameRect], NSViewAnimationEndFrameKey,
nil];
NSViewAnimation *animation = [[NSViewAnimation alloc] initWithViewAnimations:[NSArray arrayWithObject:animationInfo]];
[animation setDuration:0.2];
[animation setAnimationCurve:NSAnimationLinear];
[animation startAnimation];
[animation release];
} else {
[self setFrameOrigin:newFrameOrigin];
}
}
This is working with NSAnimationLinear, and the default NSAnimationEaseInOut, but what I actually want is merely the sense of deceleration, which I assume NSAnimationEaseOut is supposed to do. For some reason, when I use that however, the view snaps immediately to the frame it should end at, then animates sliding back to where the cursor dropped it (the start frame), then snaps back to (what should be) the end frame.
All the other modes (NSAnimationLinear, NSAnimationEaseIn, NSAnimationEaseInOut) seem to work just fine. Am I misunderstanding the purpose of NSAnimationEaseOut?
For some reason you have to flip the start and end frames to get NSAnimationEastOut to work. Plus, you need to set an animation delegate so you can be notified when the animation ends, where you must then manually set the view's frame to the original end frame.

How do I trigger a callback when a NSAnimationContext ends?

I have an animation which moves some views around. When this animation completes I want the window to recalculate the keyview loop. My code is simmilar to the follow mock code:
[NSAnimationContext beginGrouping];
[newView setAlpha: 0.0]; //hide newView
[self addSubView:newView];
//position the views
[[oldView animator] setFrame: newFrame1];
[[newView animator] setFrame: newFrame2];
[[newView animator] setAlpha: 1.0]; //fade-in newView
[NSAnimationContext endGrouping];
[[self window] recalculateKeyViewLoop];
The problem with this code is that recalculateKeyViewLoop is called before the views are in their new positions which means that the keyviewloop is wrong.
How do I fix this?
My first though is to call recalculateKeyViewLoop in a callback from when the animation ends but I can't figure out how to do this.
Something that's not so obvious, or at least wasn't to me, is that there are two animations going on when you do a setFrame:, with keys frameSize and frameOrigin.
Depending on what your original and final frames are you may need to register yourself as a delegate for one or both of them.
I'd also recommend that you make a copy of the animation you get back from -animationForKey: and store your modified copy in the animations dictionary of your object. This way your delegate will only be called at the conclusion of that particular objects' animator duration, versus all objects animating that key.
eg.
CAAnimation *animation = [[view animationForKey:#"frameOrigin"] copy];
animation.delegate = self;
[view setAnimations:[NSDictionary dictionaryWithObject:animation forKey:#"frameOrigin"]];
In this way your animation object will supersede the default animation object for that view. Then implement whichever delegate methods you're interested in.
You should be able to send -animationForKey: to your views to get a CAAnimation instance, then set yourself as its delegate and implement the method that Adam mentioned.
if you use CAAnimation this has an animationDidStop:finished: delegate method..
http://developer.apple.com/documentation/GraphicsImaging/Reference/CAAnimation_class/Introduction/Introduction.html#//apple_ref/occ/cl/CAAnimation
Hope this helps
You can use a completion handler like this:
[NSAnimationContext runAnimationGroup:^(NSAnimationContext *context){
// Start some animations.
[[myView animator] setFrameSize:newViewSize];
[[myWindow animator] setFrame:newWindowFrame display:YES];
} completionHandler:^{
// This block will be invoked when all of the animations started above have completed or been cancelled.
NSLog(#"All done!");
}];
Check out my post here: How would I do this iOS animation on OSX?
I wrote a class that handles this for you, using blocks. Hopefully your target allows blocks! :)
If you are animating an NSWindow (as opposed to an NSView), the other answers will not work and you should do this instead:
CAAnimation *animation = [CABasicAnimation animation];
animation.delegate = self;
self.window.animations = #{#"frame": animation};
[[self.window animator] setFrame:NSMakeRect(0, 0, 400, 200) display:YES];
which will then call the animationDidStop:finished: method on your delegate (which in the above code would be self)