I have a UIView and I am animating it.
The thing here is that I need to release theView once it is animated out.
originalRECT = [[UIScreen mainScreen] bounds];
if(theView)
{
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.3];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
theView setFrame = originalRECT;
[UIView commitAnimations];
[theView autorelease];
theView = nil;
}
So I know the code is setting theView to nil, but the animation does finish ok (No SIGABRT or something like that)
Or is there a callback function I can use to know that the view disappeared? How can I use a function like that in this case?
Thanks!
Few things -
First of all if you want to be sure you can use:
[UIView animateWithDuration:1.0
delay:0.0
options:UIViewAnimationCurveEaseInOut
animations:^ {
//your animation
theView setFrame = originalRECT;
}
completion:^(BOOL finished) {
//Animation finished you can release
[theView release];
}];
second - why do you use autoRelease and not release?
[theView release];
Third - Just for w meeter you don't know. USE ARC it will make your life a bit easier. You can read more here ARC tutorial
Related
I have set the animation like seen in below image. In which UIbutton move from left to right and then top to bottom. Animation work correctly but after completion of animation UIButton comes to its original place before the segue perform. so, it's not look good. I want to set that after the completion of animation UIButton can't come to it's own place before segue .
Here is my try with Image.
//Move button Left to Right
- (IBAction)btnEasy:(id)sender {
Easy=YES;
NSLog(#"your x is: %f ", self.btnEasy.frame.origin.x);
NSLog(#"your y is: %f ", self.btnEasy.frame.origin.y);
x1=self.btnEasy.frame.origin.x;
y1=self.btnEasy.frame.origin.y;
CGRect screenRect = [[UIScreen mainScreen] bounds];
[UIView animateWithDuration:1.150 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
self.btnEasy.frame = CGRectMake(screenRect.size.width/1.80, self.btnEasy.frame.origin.y, self.btnEasy.frame.size.width, self.btnEasy.frame.size.height);
[self performSelector:#selector(btneasyanimation) withObject:self afterDelay:1.160 ];}
completion:^(BOOL finished) {
}];
//Move Button top to Bottom
if (Easy==YES) {
if (isiPad2 || isiPadAir || isiPadRatina) {
//[self.view layoutIfNeeded];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:1.0];
[_btnEasy setFrame:CGRectMake(self.view.frame.origin.x+290, self.view.frame.origin.y+900, self.btnEasy.frame.size.width, self.btnEasy.frame.size.height)];
[UIView commitAnimations];
}
else if (isiPhone4s) {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:1.0];
[_btnEasy setFrame:CGRectMake(self.view.frame.origin.x+92, self.view.frame.origin.y+428, self.btnEasy.frame.size.width, self.btnEasy.frame.size.height)];
[UIView commitAnimations];
}
}
[self performSelector:#selector(segueeMethod) withObject:self afterDelay:1.160 ];
Image :-
If you are not placing directly the button given it the frame, thus using autolayout (autoresize will end with the same effect). You need to explicitly use autolayout, retain a reference to your constraints and update them (you can search here how to do that) and then set the UIView animation block [button layoutIfNeeded]
You can see a detailed answer about it in this answer
There is an easy and quick way that will work with your current implementation. Provided you know exactly where you want the view to be once the animation is done, you can do the following:
in UIView animateWithDuration: ... assign the final transform (position & orientation) of the view in the completion block, i.e.:
completion:^(BOOL finished) {
// Assign views transform and appearance here, for when the animation completes
}
Hope that helps.
I have a view currently on the screen and I would like to move it off the screen during an animation. Its current position is: CGRectMake(0, 168, 320, 50); and I would like to move it to y postion 218.
Here is my code:
[UIView beginAnimations:Nil context:NULL];
[UIView setAnimationDuration:0.3];
self.optionsView.frame = CGRectMake(0, 218, 320, 50);
[UIView commitAnimations];
Thanks in advance. Nothing is happening, the view isnt moving off screen.
Edit: When the app launches the view is off screen, i then call:
[UIView beginAnimations:Nil context:NULL];
[UIView setAnimationDuration:0.3];
self.optionsView.frame = CGRectMake(0, 168, 320, 50);
[UIView commitAnimations];
to bring the view into the main view. The problem I have is making the view go back off screen again with:
[UIView beginAnimations:Nil context:NULL];
[UIView setAnimationDuration:0.3];
self.optionsView.frame = CGRectMake(0, 218, 320, 50);
[UIView commitAnimations];
It must be noted that in order to get the view to be off screen on app launch I call:
-(void) viewDidLayoutSubviews{
self.optionsView.frame = CGRectMake(0, 218, 320, 50);
}
Update: I am also using the camera, i think dismissing the camera is affecting the layouts
I've animated the position of views as follows:
// 'frame' variable previously declared
// 'completion' block previously declared
[UIView animateWithDuration:0.3f
delay:0.0f
options:UIViewAnimationOptionCurveEaseInOut
animations:^{
[_someView setFrame:frame];
}
completion:^(BOOL finished){
if (completion) {
completion();
}
}];
Have you tried it that way?
As Martin Koles has said, the block-based approach to view animation is preferred. The following is in the reference doc for UIView:
Use of the methods in this section is discouraged in iOS 4 and later.
Use the block-based animation methods instead.
https://developer.apple.com/library/ios/documentation/uikit/reference/uiview_class/UIView/UIView.html
Use block instead:
[UIView transitionWithView:self.view duration:0.3 options:UIViewAnimationOptionCurveEaseInOut animations:^{
// final view elements attributes goes here
} completion:nil];
This is the modern way of doing animations. You can even specify a completion block, something that should happed after the animation is done, if needed.
Try using this
[UIView animateWithDuration:0.3 delay:0 options: UIViewAnimationOptionCurveLinear
animations:^{
self.optionsView.frame = CGRectMake(0, 218, 320, 50);
} completion:nil];
Worked fine with me.
Make sure the view is connected in the xib to its proper object.
I'm implementing my own Navigation Controller and I'm faking the animation of adding the new view as in UINavigationContoller.
The following code works great, however if I move -addSubview:, before UIView animation call, it will animate in ios7, but not in ios6, the question is why? (I mean, why does it would make a difference, as animation will be scheduled and executed asynch, right? Or I might suppose It will somehow affect the starting state of animation?)
- (void)didAddViewControllerInNavigationStack:(NSArray*)navigationStack
{
if (self.activeViewController) {
[self.activeViewController viewWillDisappear:YES];
[self.activeViewController viewDidDisappear:YES];
}
self.activeViewController = navigationStack.firstObject;
if (!self.activeViewController) return;
CGRect windowRect = [[UIScreen mainScreen] bounds];
windowRect.origin.x = windowRect.size.width;
self.activeViewController.view.frame = windowRect;
[self.activeViewController viewWillAppear:YES];
[UIView transitionWithView:self.view
duration:0.32
options:UIViewAnimationOptionCurveEaseOut
animations:^ { self.activeViewController.view.frame = [[UIScreen mainScreen] bounds]; }
completion:^(BOOL isDone){[self.activeViewController viewDidAppear:YES];}];
[self.view addSubview:self.activeViewController.view];
[UIView commitAnimations];
}
From the documentation of transitionWithView:duration:options:animations:completion:, it is said you should add the subview inside the animation block:
The block you specify in the animations parameter contains whatever state changes you want to make. You can use this block to add, remove, show, or hide subviews of the specified view.
Also, you are calling commitAnimations without having called beginAnimations:context:. You are mixing things here. Block-based animation API does not need the begin-end API.
Your code should be:
[UIView transitionWithView:self.view
duration:0.32
options:UIViewAnimationOptionCurveEaseOut
animations:^ { [self.view addSubview:self.activeViewController.view]; self.activeViewController.view.frame = [[UIScreen mainScreen] bounds]; }
completion:^(BOOL isDone){[self.activeViewController viewDidAppear:YES];}];
I tried animating a sequence of UIViews from a mutable array to simulate this animation
for(int k = 0; k< [imageViewCarrier count] ; k++){
UIView *transformingView = [imageViewCarrier objectAtIndex:k];
[UIView animateWithDuration:30.0 animations:^{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:30.0];
[UIView setAnimationDelegate:self];
[UIView transitionFromView:transformingView toView:splicedImageView duration:3 options:UIViewAnimationOptionTransitionFlipFromLeft completion:NULL];
[UIView commitAnimations];
}completion:^(BOOL finished){
NSLog(#"Transition done");
}];
}
The animation seems to be too fast. Any suggestions on this. Did search some documentation but couldn't figure it out. Some help would be greatly appreciated!
Hm, I think you might be doing it the wrong way. If memory serves me, when using [UIView animinateWithDuration:animiations:completion:], you shouldn't call [UIView beginAnimations:nil context:NULL]; and [UIView commitAnimations]; or setAnimationDelegate: or setAnimationDuration: for that matter, since they are the old way of animating views that you had to use before the block-based methods were introduced.
I'd try leaving those out and see what happens. Also, note that the duration parameter is in seconds, so 30.0 seems a bit too long.
And just a style note: the "proper" Objective-C way to iterate through a collection is as follows:
for(UIView* view in imageViewCarrier){
[view doSomething];
}
I'd like to animate the transition from a subview back to the super view.
I display the subview using:
[UIView beginAnimations:#"curlup" context:nil];
[UIView setAnimationDelegate:self];
[UIView setAnimationDuration:.5];
[UIView setAnimationTransition:UIViewAnimationTransitionCurlUp forView:self.view cache:YES];
[self.view addSubview:self.mysubview.view];
[UIView commitAnimations];
The above works fine. It's going back to the super view that I don't get any animation:
[UIView beginAnimations:#"curldown" context:nil];
[UIView setAnimationDelegate:self];
[UIView setAnimationDuration:.5];
[UIView setAnimationTransition:UIViewAnimationTransitionCurlDown forView:self.view cache:YES];
[self.view removeFromSuperview];
[UIView commitAnimations];
Is there something different I should be doing to get the subview to animate when removed?
If you're targeting iOS 4.0 upwards you can use animation blocks instead:
[UIView animateWithDuration:0.2
animations:^{view.alpha = 0.0;}
completion:^(BOOL finished){ [view removeFromSuperview]; }];
(above code comes from Apple's UIView documentation)
I think you need to do forView:self.view.superview instead, to be consistent with what you are doing when you are adding, because in this case the self.view is the child, and so you would need to do it on the parent.
JosephH answer in Swift:
UIView.animateWithDuration(0.2, animations: {view.alpha = 0.0},
completion: {(value: Bool) in
view.removeFromSuperview()
})
Although approach with sending removeFromSuperview message from animation completion block works fine for most cases, sometimes there is no way to prevent a view from immediate removal from view hierarchy.
For example, MKMapView removes its subviews after it receives message removeAnnotations, and there is no "animated" alternative for this message in the API.
Nonetheless the following code allows you to do whatever you like with a visual clone of a view after it's been removed from superview or even deallocated:
UIView * snapshotView = [view snapshotViewAfterScreenUpdates:NO];
snapshotView.frame = view.frame;
[[view superview] insertSubview:snapshotView aboveSubview:view];
// Calling API function that implicitly triggers removeFromSuperview for view
[mapView removeAnnotation: annotation];
// Safely animate snapshotView and release it when animation is finished
[UIView animateWithDuration:1.0
snapshotView.alpha = 0.0;
}
completion:^(BOOL finished) {
[snapshotView removeFromSuperview];
}];
Example below:
func removeSpinningGear(cell: LocalSongsCollectionViewCell) {
UIView.animate(withDuration: 1.0, delay: 0.0, options: UIView.AnimationOptions.curveLinear, animations: {
cell.spinningGearBtn.alpha = 0.0
}) { _ in
cell.spinningGearBtn.removeFromSuperview()
}
}