How to perform operations in each iteration of UIView animateWithDuration - ios5

I am changing the size of a view using animation and I need to change the image of imageview inside that view in every step of the animation. The image depends on the view size that's why I want to do so. I have tried to do that in the animations: block, but it seems to be called only once and not for each iteration as I expected.
How can I perform some operations during each iteration of UIView animateWithDuration:animations:. Or maybe there is another solution for my problem?
P.S. I have tried to use completion: block, but it doesn't solve my problem correctly as I want to achieve smooth change of images.

if i give you simple answer, the answer is no...
but i have an alternative for this make a function which you can call recursively like..
-(void)animationRecursive
{
[UIView animateWithDuration:0.001 animations:^{
// Here set frame slide different from last frame use incremental variables
// for x,y,width,height
//yourImageView.frame = set frame
//yourImageView.image = set image
} completion:^(BOOL finished) {
if(![yourImage.frame isEqualToString NSStringFromCGRect(yourFinalCGRectAfterAnimation)]
{
[self animationRecursive];
}
}];
}
hope this will help you.............

Related

Make move animation permanent in iOS

I am trying to make a simple application where there are 3 buttons. When user clicks any of the button, they are animated(moved) to their new positions! All this works from this code:
[UIView animateWithDuration:1.2
delay:0.1
options: UIViewAnimationCurveEaseOut
animations:^
{
//Moving the Sum (UIButton which will move through this animation)
CGRect frame = Sum.frame;
frame.origin.y = -20;
frame.origin.x = (-120);
Sum.frame = frame;
.....
....
}
completion:^(BOOL finished)
{
NSLog(#"Completed");
//adding subview after the animation is complete! newView is an example!
[self.view addSubview:newView];}];
The Problem is that once i add a subview to the main view, All buttons come back to their old position! meaning they weren't moved permanently.. how can i solve this? Plz help guys!
What happens when you add a view? A layout is performed. You could have done two mistakes
You are using autolayout.
If you are using autolayout, changing frames directly is not advised and a relayout will update the views to their original position using current constraints.
You are setting the frame position in layoutSubviews, viewWillLayout or viewDidLayout.
Check where you are setting the original position. Can the method be called multiple times?
You have save the X,Y Position of the new frame & then set this frame by coding.

iPhone iOS what is the correct way to do actions with UIView animateWithDuration block?

I'm wandering what is the correct way to do "long" actions in response to user events. For example, I have this slide to cancel block that animates itself off screen over 0.5 seconds. The [self coreDataAction] may take about 0.3 seconds itself.
I want to ensure that the action completes once the user sees the end of the animation ( I do not want the user to accidentally navigate to a different controller or close the app thinking that the action is done).
Where should I put the [self coreDataAction]; in this case? Above the block, within the block or in the completion block?
//should I put it here?
CGPoint slideToCancelCenter = slideToCancel.view.center;
[UIView animateWithDuration:0.5 animations:^{
self.goToSleepButton.center = slideToCancelCenter;
[UIView setAnimationDuration:0.5];
CGPoint sliderCenter = slideToCancel.view.center;
sliderCenter.y += slideToCancel.view.bounds.size.height;
slideToCancel.view.center = sliderCenter;
//should I put it here?
// [self coreDataAction];
} completion:^(BOOL finished) {
//should I put it here?
} ];
A better way to handle this might be to animate the view on-screen then start the coreDataAction in the completion handler. Once the coreDataAction method execution is complete you can call a method to animate the slide to cancel view off-screen.
Assuming [self coreDataAction] executes on the main thread, I would say you should put it on the first line to ensure that the method is complete by the time the animation is done.

Unusual animateWithDuration behaviour in viewDidLoad

I'm experiencing some unusual behaviour when performing an animated transform on a UIImageView. The code in the method below makes the image appear like it's rocking from side-to-side:
-(void) shakeAnimation
{
float degrees = 30; //the value in degrees
imgShake.autoresizingMask = UIViewAutoresizingNone;
[UIView animateWithDuration:0.20f delay:0 options:(UIViewAnimationOptionCurveLinear | UIViewAnimationOptionAllowUserInteraction | UIViewAnimationOptionAutoreverse | UIViewAnimationOptionRepeat) animations:^{
imgShake.transform = CGAffineTransformMakeRotation(degrees*M_PI/180);
} completion:^(BOOL finished) {
imgShake.transform = CGAffineTransformMakeRotation(1*M_PI/180);
NSLog(#"Shake finished");
}];
}
The problem comes with where i call the method. If i call the method in viewDidAppear the animation seems to work perfectly...but for other reasons i need to call it in viewDidLoad. When i call the method from viewDidLoad the animation functions but not at the speed specified by animateWithDuration. It's much slower, probably 0.70f. Is there something i could be missing here?
You never need to call it in viewDidLoad. That's simply wrong and it won't work. Move the code into viewDidAppear. If you have reasons to put it into viewDidLoad, fix the reasons!
EDIT: You never know when viewDidLoad is called - it can even be called multiple times for one controller. Usually the problem with slow animations is caused by a collision between two animations. For example, if your controller is animated to the screen by a UINavigationController, your animation will collide with the "push" animation and they will be slow. That's why you are supposed to use viewDidAppear because when this method is called you know that the controller is displayed and the "appear" animation has ended.
Call the method using some delay.
[self performSelector:#selector(shakeAnimation) withObject: afterDelay:2.0]

Make cell imageView fly in with animation

How can I make imageView property of my cells fly in one by one?
I can now make them fly in, but only all at once.
And is it good for performance to do something like this?
Thank you!
Use the indexPath.row to calculate a delay.
float animationDelay = 0.2f;
[UIView animateWithDuration:0.3f
delay:animationDelay * indexPath.row
options:0
animations:^{
cell.imageView.transform = CGAffineTransformMakeScale(1.0f, 1.0f);
} completion:^{}];
This will delay every row by 0.2 seconds relative to the row above it. Of course this will only work when you initially load the table, but I guess this is what you're trying to animate? When you start scrolling and new cells are loaded, you probably should set the delay to zero. Otherwise the images will take a while to show up.
To achieve this I recommend introducing a BOOL ivar called loadingTheFirstTime that is set to YES initially (in the init or awakeFromNib methods). Then you can set that to NO when the table is shown the first time. When creating the cells you should then check for this variable first to see if you have to add a delay.
I supposed here that you are in cellForRowAtIndexPath:. Change your animation with that :
[UIView animateWithDuration: 3.0
delay: indexPath.row
options: UIViewAnimationCurveLinear
animations: ^{
cell.imageView.transform = CGAffineTransformMakeScale(1.0f, 1.0f);
}
completion:^(BOOL finished) {
}];
The animations will load with 1 sec of interval. If you're not in this function, set a tag to your cells when you create them, and put that tag in the delay.
Maybe set up a method where there is a for loop that runs through every cell and runs the animation for each time through the loop? Regarding performance, I have no idea. I would't imagine it would be GOOD for performance, especially if there are a lot of cells, but you can always try it and find out! :)

completion block of uiview animate never called if view disappear

i noticed some strange behavior. When i start a animation and change the View (the view will not dismissed!), the completion handler never get called.
[UIView animateWithDuration:0.1f
delay:0.0f
options:UIViewAnimationCurveEaseOut
animations:^(void){
[myView setHidden:YES];
myLabel.alpha = 0.0f;
someOtherView.frame = CGRectMake(130, bubbleBigRect.origin.y, 61, 65);
[button setHidden:YES];
}
completion:^(BOOL finished){
NSLog(#"Complete %d",finished);
[imageVIew setImage:[UIImage imageNamed:#"myPng.png"]];
}];
}
is there any solution for this?
Don't know where to write it, but I get the same thing that you have, but in my case the completion block was sometimes called. It might be same thing.
I found out that if in the animation block has nothing was animate- for example, if you set alpha=0 to uiview that is alpha is already 0, or you set content offset to UIScrollView to the same content offset (like in my case), the completion block not called.
Put this in your animation block, and put everything you want to do on completion in YOUR_SELECTOR method. You can now do whatever you want with your view and still have a way of executing something on completion!
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(YOUR_SELECTOR)];
In my case the view which I was animating has its frame set to (0,-568,320,568) and after animation I forget to change the frame to its required position i.e. (0,0,320,568) so the completion block was not being called. Changing the frame of the animated view did the job for me. So I can say if for instance the view has nothing to show(as the frame was not set in visible region). The completion block may not called.
Move your call to [myView setHidden:YES] from the animations block to the completion block. I think that will probably help. You can still set the alpha of myView to 0 during the animation block (if you want it to fade out), or before the entire call to -[UIView animateWithDuration:delay:options:animations:completion:] if you want it to disappear right away.