UIView animation not working when used with DCRoundSwitch - objective-c

I have done following code for animation inside a selector method of custom UISwitch DCRoundSwitch.
if ([[[App.remindersArray objectAtIndex:0] objectAtIndex:3]isEqualToString:#"YES"]){
[firstReminderOnOffButton setSelected:YES];
[swtchDailyReminder setOn:YES];
imgviewDailyReminder.image=[UIImage imageNamed:#"nDailyReminder_On_1.png"];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.35];
[UIView setAnimationDidStopSelector:#selector(animateFadingIn)];
[UIView setAnimationDelegate:self];
imgviewDailyReminderAnimation.alpha = 1.0;
[UIView commitAnimations];
}
else
{
[firstReminderOnOffButton setSelected:NO];
[swtchDailyReminder setOn:NO];
imgviewDailyReminder.image=[UIImage imageNamed:#"xDailyReminder_OFF.png"];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.35];
[UIView setAnimationDidStopSelector:#selector(animateFadingIn)];
[UIView setAnimationDelegate:self];
imgviewDailyReminderAnimation.alpha = 0.0;
[UIView commitAnimations];
}
The problem is animation is working properly when above code is called from normal UISwitch,but not working when called from DCRoundSwitch.
Also tried to resolve by using UIView block animation....but still facing the problem.
Please guide me.

The issue is in DCRoundSwitch's animation block. No CATransaction is created in the completion block of setOn:animated:ignoreControlEvents: resulting in [UIView animateWithDuration...] methods not working properly when called in response to the switch's value being changed.
To solve the problem, just change:
if (previousOn != on && !ignoreControlEvents)
[self sendActionsForControlEvents:UIControlEventValueChanged];
To:
if (previousOn != on && !ignoreControlEvents)
{
[CATransaction begin];
[CATransaction setDisableActions:NO];
[self sendActionsForControlEvents:UIControlEventValueChanged];
[CATransaction commit];
}
That should do it

i have used this below code. which works correctly.
Please follow up this thread
https://github.com/domesticcatsoftware/DCRoundSwitch/issues/12
U can just go to the Class which is using this DCRoundSwitch , on that class's dealloc method put this line.
- (void)dealloc
{
[self.MyDCRoundSwitch removeTarget:nil
action:NULL
forControlEvents:UIControlEventAllEvents];
[super dealloc];
}

Related

setAnimationDidStopSelector: not getting called

I know this question gets asked a lot but i have tried all the other answers and i can't figure out why the animation stop selector does not get called. Here is the code:
-(void) moveImage:(UIImageView *)image duration:(NSTimeInterval)duration curve:(int)curve x:(CGFloat)x y:(CGFloat)y annKey:(NSString *) annKey{
[UIView setAnimationDelegate:self];
[UIView setAnimationDuration:duration];
[UIView setAnimationCurve:curve];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDidStopSelector:#selector(animationFinished:finished:context:)];
CGAffineTransform transform = CGAffineTransformMakeTranslation(x, y);
image.transform = transform;
[UIView beginAnimations:annKey context:NULL];
[UIView commitAnimations];
}
This is the main animation function that gets sent all the correct parameters.
- (void)animationFinished:(NSString *)animationID finished:(BOOL)finished context:(void *)context
{
if ([animationID isEqualToString:#"Burn"])
{
NSLog(#"Animation: %# has finished.",animationID);
}
NSLog(#"This does not get called, why not?");
}
None of my NSLogs display text. What am i doing wrong?
You need tho do -
[UIView beginAnimations:annKey context:NULL];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(animationFinished:finished:context:)];
// Now define rest.
[UIView setAnimationDuration:duration];
[UIView setAnimationCurve:curve];
[UIView setAnimationBeginsFromCurrentState:YES];
CGAffineTransform transform = CGAffineTransformMakeTranslation(x, y);
image.transform = transform;
[UIView commitAnimations];
Not sure what the problem is, but you really shouldn't be using beginAnimations/commitAnimations. Instead, use block animations. You define the completion code directly in the completion portion of the call.
[UIView animateWithDuration:2.0
delay:0.0
options:UIViewAnimationOptionCurveEaseOut
animations:^{
// animation code
}
completion:^(BOOL finished){
// completion code
}];

custom UIView animation in dismissModalViewController

Where is the correct place to put custom animation code for dismissing a modalviewcontroller.
I tried putting the following into viewdiddisappear, viewwilldisappear but doesn't behave correctly. Any thoughts? THanks!!
[UIView beginAnimations:#"suck" context:NULL];
[UIView setAnimationDuration:1.0];
[UIView setAnimationTransition:103 forView:self.navigationController.view cache:YES];
[UIView setAnimationPosition:CGPointMake(260, 431)];
[UIView commitAnimations];
Try this:
UIViewController *myController = [[[MyViewController alloc] init] autorelease];
UIViewAnimationTransition transition = UIViewAnimationTransitionCurlUp; // or whatever effect you want
[UIView beginAnimations:nil context:nil];
[UIView setAnimationTransition:transition forView:[self window] cache:YES];
[navController presentModalViewController:myController animated:NO]; // or dismissModalViewController in your case
[UIView commitAnimations];
I think I figured it out. I followed the example in:
http://developer.apple.com/library/ios/#samplecode/BubbleLevel/Introduction/Intro.html
Basically removed the second view from superview and inserted the first view back in. The transition works correctly afterwords.
THanks for the help.

Triggering a method after a delay without abusing [UIView animateWithDuration]?

I have a UIViewController that should control 2 UIImageViews to fade in.
I managed to animate them using the UIView animateWithDuration method, like this:
[UIView animateWithDuration:1.5
animations:^{
[mFrontpageTitle setAlpha:0];
[mFrontpageTitle setAlpha:1];
}
completion:^(BOOL finished){
[self AnimatePause];
}];
and
-(void)AnimatePause {
[UIView animateWithDuration:5.0
animations:^{
[mFrontpageTitle setAlpha:0.99];
[mFrontpageTitle setAlpha:1];
}
completion:^(BOOL finished){
[self AnimateAuthor];
}];
which fires the next animation. Now, creating a transition from .99 to 1.0 is not very clean.
Is there a better way to trigger a block or sending a message by just defining a duration?
thanks
Zuppa
NSTimeInterval delay = 1.5; //in seconds
[self performSelector:#selector(myMethod) withObject:nil afterDelay:delay];

method "wait your turn"!

hi
when certain events occur, I call a number of methods (unlocked trophies in a game) they do appear and disappear a sub-view.
Crash (rightly) occurs when these events occur simultaneously and overlap.
How do I make sure that " wait your turn :) "?
thanks
-(void)trofeiLaunch:(int)x {
CGRect loseFrame = CGRectMake(0, 0, 480, 320);
TrofeoView = [[UIView alloc] initWithFrame:loseFrame];
TrofeoView.alpha = 0.0;
[UIView beginAnimations:nil context:self];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
[UIView setAnimationDuration:0.5];
[UIImageView setAnimationDelegate:self];
TrofeoView.alpha = 1.0;
[UIView setAnimationDidStopSelector:#selector(bridgeTrofei)];
[UIView commitAnimations];
[self.view addSubview:TrofeoView];
[TrofeoView release];
....
}
-(void)bridgeTrofei {
TrofeoView.alpha = 1.0;
[UIView beginAnimations:nil context:self];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
[UIView setAnimationDuration:0.5];
[UIView setAnimationDelegate:self];
TrofeoView.alpha = 0.0;
[UIView commitAnimations];
[self performSelector:#selector(deleteTrofei) withObject:self afterDelay:1.0];
}
-(void)deleteTrofei {
[TrofeoView removeFromSuperview];
NSLog(#"delete");
}
Crash (rightly) occurs when these events occur simultaneously and overlap.
How do I make sure that " wait your turn :) "?
thanks
If the second animation starts before the first animation is complete, TrofeoView will get reassigned and you will lose the earlier reference. You also flout memory management rules when you release TrofeoView in 'trofeiLaunch:` method. You use this variable again later with having taken ownership. You should only release an object if you are done with it which you are not.
I think the most important thing going down this path is to make sure that three methods refer to the correct object. First one is ok by default so you need to handle the next two. I have modified your code to do that.
- (IBAction)start {
animatingView = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 200, 200)];
animatingView.backgroundColor = [UIColor greenColor];
animatingView.alpha = 0.0;
[UIView beginAnimations:#"Trophy Display" context:animatingView];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
[UIView setAnimationDuration:0.5];
[UIImageView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(animationDidStop:finished:context:)];
animatingView.alpha = 1.0;
[UIView commitAnimations];
[self.window addSubview:animatingView];
}
- (void)animationDidStop:(NSString*)animationID finished:(NSNumber*)finished context:(void *)context {
if ( [animationID isEqualToString:#"Trophy Display"] ) {
UIView *aView = (UIView *)context;
[UIView beginAnimations:nil context:aView];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
[UIView setAnimationDuration:0.5];
[UIView setAnimationDelegate:self];
aView.alpha = 0.0;
[UIView commitAnimations];
[self performSelector:#selector(finishAnimation:) withObject:aView afterDelay:1.0];
}
}
- (void)finishAnimation:(UIView*)aView {
[aView removeFromSuperview];
[aView release];
}
I pass the view via context to the second method and withObject: part to the third method. I am hoping the code is self explanatory. Let me know if you don't get this.
Next point is about whether this is the right way. Can't you manage this using an array? Push only if there is no view in display.

Trying to fade in a UIView without success

I am trying to fade in a UIView as a subview of my main view. The UIView I am trying to fade in has the dimensions of 320x55.
I setup the view and a timer;
secondView.frame = CGRectMake(0, 361, 320, 55);
secondView.alpha = 0.0;
[self.view addSubview:secondView];
[NSTimer scheduledTimerWithTimeInterval:.5 target:self selector:#selector(fadeView) userInfo:NO repeats:NO];
The timer triggers the following code;
secondView.alpha = 1.0;
CABasicAnimation *fadeInAnimation;
fadeInAnimation = [CABasicAnimation animationWithKeyPath:#"opacity"];
fadeInAnimation.duration = 1.5;
fadeInAnimation.fromValue = [NSNumber numberWithFloat:0.0];
fadeInAnimation.toValue = [NSNumber numberWithFloat:1.0];
[fadeInAnimation setDelegate:self];
[secondView.layer addAnimation:fadeInAnimation forKey:#"animateOpacity"];
My secondView is connected in Interface Builder and responds to other messages but I can't see anything happening on screen.
Can anyone please help me figure out what's going on here?
Thanks,
Ricky.
In reply to a following recommendation:
I'm a bit unsure here. Initially I put this code in (because I see secondView as an instance of UIView?):
[secondView beginAnimations:nil context:NULL];
[secondView setAnimationDuration:0.5];
[secondView setAlpha:1.0];
[secondView commitAnimations];
I then tried your suggestion which didn't produce warnings or errors, but it still does brings nothing to the surface:
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
[secondView setAlpha:1.0];
[UIView commitAnimations];
Thanks! Ricky.
You should be able to do this a bit simpler. Have you tried something like this?
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
[secondView setAlpha:1.0];
[UIView commitAnimations];
it seems to me that one thing you're missing is that your view may already have an alpha of 1.0. make sure the alpha is 0 (or whatever you desire it to be) prior to the animation call.
i prefer to use block animations for this. it's cleaner and more self-contained.
secondView.alpha = 0.0f;
[UIView animateWithDuration:1.5 animations:^() {
secondView.alpha = 1.0f;
}];
This won't answer your question if you insist on using CoreAnimations, but for iPhoneOS it's much easier to use animation blocks for UIView animations.
secondView.alpha = 0.0f;
[UIView beginAnimations:#"fadeInSecondView" context:NULL];
[UIView setAnimationDuration:1.5];
secondView.alpha = 1.0f;
[UIView commitAnimations];
Also, you can invoke a delegate in delayed time with
[self performSelector:#selector(fadeView) withObject:nil afterDelay:0.5];
Here is also a good alternative with many options and easy to use.
[secondViewController.view setAlpha:0.0];
[UIView animateWithDuration:1.5
delay:0.0
options:UIViewAnimationOptionCurveEaseIn // See other options
animations:^{
[secondViewController.view setAlpha:1.0];
}
completion:^(BOOL finished) {
// Completion Block
}];