performSelector is calling new in if loop - ios

i have
if (_moves <=19) {
[self performSelector:#selector(changeLabelState:) withObject:nil afterDelay: 1.0];
}
And the Method:
- (void)changeLabelState:(NSTimer *)timer
{
[UIView transitionWithView:self.movesLeftLabel duration:0.25 options:UIViewAnimationOptionTransitionCrossDissolve animations:^{
self.movesLeftLabel.textColor = [UIColor whiteColor];
} completion:^(BOOL finished) {
[UIView transitionWithView:self.movesLeftLabel duration:0.25 options:UIViewAnimationOptionTransitionCrossDissolve animations:^{
self.movesLeftLabel.textColor = [UIColor darkGrayColor];
} completion:^(BOOL finished) {
}];
}];
[self performSelector:#selector(changeLabelState:) withObject:nil afterDelay:1.5];
}
So if _moves = 19, everything works fine. its changing to white and back to grey. but if the _moves = 18, it calls another time, and the transition is too fast.
how can i do it that he is not calling it another time?

If you wrote you code in loop, and you do not want to perform selector more than one time try to add 'break;' after perform
if (_moves <=19) {
[self performSelector:#selector(changeLabelState:) withObject:nil afterDelay: 1.0];
break;
}
or, if you want, change clause to
if (_moves ==19) {
[self performSelector:#selector(changeLabelState:) withObject:nil afterDelay: 1.0];
}

Related

Restart animation when comes back in foreground

So i was trying my hands on animation. I have a UIlabel which i want to fade in on and fade out after certain period.
I successfully done it as shown in the first answer with the help of timer.
Animation done as shown in Answer 1
Now i want to restart this animation when my app comes foreground.
Problems :-
What should i do to restart animations?
I want that when app comes in foreground, UIlabel should act as if this is the first time i am starting animation. Basically remove all animation on UIlabel and do start animation fresh.
use like add the following method in your ViewDidLoad
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(myMethod) name:UIApplicationWillEnterForegroundNotification object:nil];
-(void)myMethod
{
// start the beiging code here
//[self MyLabelAnimation];
[NSTimer scheduledTimerWithTimeInterval:0.0 target:self selector:#selector(MyLabelAnimation:) userInfo:nil repeats:NO];
}
You should do like this
#interface ViewController ()
{
NSTimer *timer;
}
#end
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
timer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:#selector(MyLabelAnimation:) userInfo:nil repeats:NO];
}
- (void)MyLabelAnimation:(NSTimer*) timer1 {
self->_mylabel.text = #"Hello";
[UIView animateWithDuration:0.3 animations:^{
self->_mylabel.alpha = 1.0;
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.3 delay:2.7 options:UIViewAnimationOptionCurveEaseInOut animations:^{
self->_mylabel.alpha = 0.0;
} completion:^(BOOL finished) {
self->_mylabel.text = #"Text 2";
[UIView animateWithDuration:0.3 animations:^{
self->_mylabel.alpha = 1.0;
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.3 delay:2.7 options:UIViewAnimationOptionCurveEaseInOut animations:^{
self->_mylabel.alpha = 0.0;
} completion:^(BOOL finished) {
self->_mylabel.text = #"Text 3";
[UIView animateWithDuration:0.3 animations:^{
self->_mylabel.alpha = 1.0;
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.3 delay:2.7 options:UIViewAnimationOptionCurveEaseInOut animations:^{
self->_mylabel.alpha = 0.0;
} completion:^(BOOL finished) {
self->_mylabel.text = #"Text 4";
[UIView animateWithDuration:0.3 animations:^{
self->_mylabel.alpha = 1.0;
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.0 delay:4.8 options:UIViewAnimationOptionCurveEaseInOut animations:^{
self->_mylabel.alpha = 0.0;
} completion:^(BOOL finished) {
[self viewWillAppear:YES];
}];
}];
}];
}];
}];
}];
}];
}];
}
-(void)viewWillDisappear:(BOOL)animated
{
[timer invalidate];
}
You should read Looking to understand the iOS UIViewController lifecycle carefully.
The methods your are looking to use are
viewWillAppear and viewWillDisappear
-(void) viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
[NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:#selector(MyLabelAnimation:) userInfo:nil repeats:NO];
}
// Your animation....
- (void)MyLabelAnimation:(NSTimer*) timer {
self->mylabel.text = #"Hello";
[UIView animateWithDuration:0.3 animations:^{
self->mylabel.alpha = 1.0;
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.3 delay:2.7 options:UIViewAnimationOptionCurveEaseInOut animations:^{
self->mylabel.alpha = 0.0;
} completion:^(BOOL finished) {
self->mylabel.text = #"Text 2";
[UIView animateWithDuration:0.3 animations:^{
self->mylabel.alpha = 1.0;
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.3 delay:2.7 options:UIViewAnimationOptionCurveEaseInOut animations:^{
self->mylabel.alpha = 0.0;
} completion:^(BOOL finished) {
self->mylabel.text = #"Text 3";
[UIView animateWithDuration:0.3 animations:^{
self->mylabel.alpha = 1.0;
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.3 delay:2.7 options:UIViewAnimationOptionCurveEaseInOut animations:^{
self->mylabel.alpha = 0.0;
} completion:^(BOOL finished) {
self->mylabel.text = #"Text 4";
[UIView animateWithDuration:0.3 animations:^{
self->mylabel.alpha = 1.0;
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.0 delay:4.8 options:UIViewAnimationOptionCurveEaseInOut animations:^{
self->mylabel.alpha = 0.0;
} completion:^(BOOL finished) {
[NSTimer scheduledTimerWithTimeInterval:0.0 target:self selector:#selector(MyLabelAnimation:) userInfo:nil repeats:NO];
}];
}];
}];
}];
}];
}];
}];
}];
}
Here is the answer for the question I have asked.
Inwit done it with the help of a bool variable which sets to No when app goes in background and will get set to yes when goes in foreground.
SO the next animation depends on the bool value.
Here is the link for the answer
Restart animation after pause

How to create Label text slider

I have created slider in my app. How to add loop in my code. Because my label text slide only one time but i want to label text repeat (loop) on label. How it possible?
My Label slider code
Make globalCounter as global variable
globalCounter=0;
if(nameArray.count>0){
[self changeLable];
}
Then
-(void)changeLable{
if(!(globalCounter<nameArray.count)){
return;
}
NSLog(#"globalCounter %d",globalCounter);
[UIView animateWithDuration:1
delay:0.5
options: UIViewAnimationOptionTransitionCrossDissolve
animations:^{
}
completion:^(BOOL finished) {
[lblTitle setText:[nameArray objectAtIndex:globalCounter]];
globalCounter++;
[self performSelector:#selector(changeLable) withObject:nil afterDelay:1];
}];
}
Edit
-(void)changeLable{
if(!(globalCounter<nameArray.count)){
globalCounter=0;
}
NSLog(#"globalCounter %d",globalCounter);
[UIView animateWithDuration:1
delay:0.5
options: UIViewAnimationOptionTransitionCrossDissolve
animations:^{
}
completion:^(BOOL finished) {
[lblTitle setText:[nameArray objectAtIndex:globalCounter]];
globalCounter++;
[self performSelector:#selector(changeLable) withObject:nil afterDelay:1];
}];
}
do like
globalCounter=0;
if(des.count>0){
[_label setText:[des objectAtIndex:globalCounter]];
[self changeLable];
}
and call method like
-(void)changeLable{
if(globalCounter < des.count){
[UIView animateWithDuration:0.
delay:0.5
options: UIViewAnimationOptionTransitionCrossDissolve
animations:^{
}
completion:^(BOOL finished) {
if(globalCounter>=des.count){
globalCounter=0;//set counter to zero after it exceeds array count to repeat text change round repeated
}else
{
[_label setText:[des objectAtIndex:globalCounter]];
globalCounter++;
[self performSelector:#selector(changeLable) withObject:nil afterDelay:1];
}
}];
}
}
Try below code, it may help:
-(void)changeLable{
NSLog(#"globalCounter %d",globalCounter);
[UIView animateWithDuration:1
delay:0.5
options: UIViewAnimationOptionTransitionCrossDissolve
animations:^{
[lblTitle setText:[nameArray objectAtIndex:globalCounter]];
}
completion:^(BOOL finished) {
if(globalCounter>nameArray.count)){
globalCounter=0;//set counter to zero after it exceeds array count to repeat text change round repeated
}else{
globalCounter++;
}
[self performSelector:#selector(changeLable) withObject:nil afterDelay:1];
}];
}
This is my answer brother.Sorry I could not answer immediately as I had some work.I downloaded and ran your project.First it crashes as you handled the wrong array count.So it bounds the array.After that I set the condition inside the black.
-(void)changeLable
{
NSLog(#"globalCounter %d",globalCounter);
[UIView animateWithDuration:1
delay:0.5
options: UIViewAnimationOptionTransitionCrossDissolve
animations:^{
}
completion:^(BOOL finished)
{
if(globalCounter<des.count)
{
_label.text = #"";
[_label setText:[des objectAtIndex:globalCounter]];
globalCounter++;
}
else
globalCounter=0;
[self performSelector:#selector(changeLable) withObject:nil afterDelay:1];
}];
}

Update slider value on label when slider animates

I am using slider in my app. I have done all the setup only problem i am facing is the label on which i want slider values is not updating. Have a look at my code.
I have a button which on click animates the slider. I am not able to update my label as it shows 0.0 throughout the animation.
Any help will be highly appreciated.
- (IBAction)btnClicked:(id)sender
{
[UIView animateWithDuration:10 animations:^{
[self.slider setValue:0.0 animated:true];
} completion:^(BOOL finished) {
[UIView animateWithDuration:10 animations:^{
[self.slider setValue:100.0 animated:true];
}];
}];
}
Your code is not working because you try to set the maximum value to the slider so that it is simply set that maximum value with animation nothing more. Try my code that may be help you.
Change your btnClicked with this
- (IBAction)btnClicked:(id)sender {
[self.slider setValue:0 animated:true];
[self setSliderValue:1];
}
Add this setSliderValue method
- (void)setSliderValue:(float)value {
[UIView animateWithDuration:0.2 animations:^{
[self.slider setValue:value animated:true];
} completion:^(BOOL finished) {
self.lblSliderValue.text = [NSString stringWithFormat:#"%0.0f", self.slider.value];
if (self.slider.value != self.slider.maximumValue) {
[self setSliderValue:value+1];
}
}];
}
Hope this will help you.
Try like this:
- (IBAction)btnClicked:(id)sender
{
[self.slider setValue:0.0 animated:true];
[UIView animateWithDuration:10 animations:^{
[slider addTarget:self action:#selector(sliderChanged:) forControlEvents:UIControlEventValueChanged];
} completion:^(BOOL finished) {
[UIView animateWithDuration:10 animations:^{
//[self.slider setValue:100.0 animated:true];
}];
}];
}
sliderChanged method is like this:
- (void)sliderChanged:(UISlider *)slider {
self.label.text = [NSString stringWithFormat:#"%0.2f", slider.value];
}

Transition view on the same ViewContoller

I am trying to flip transition on the same ViewController, I have a button for trigger transition. I want to change theme color when i press to button via flip transition.
i used this code part:
- (IBAction)changeThemeButtonTapped:(id)sender
{
int tempThemeColor = [[NSUserDefaults standardUserDefaults]integerForKey:#"themeColor"];
if (tempThemeColor == 10) {
[self loadTheme];
[UIView transitionFromView:self.view
toView:self.view
duration:1.0
options:UIViewAnimationOptionTransitionFlipFromLeft
completion:^(BOOL finished) {
NSLog(#"finished");
}];
}else{
[self loadTheme];
[UIView transitionFromView:self.view
toView:self.view
duration:1.0
options:UIViewAnimationOptionTransitionFlipFromRight
completion:^(BOOL finished) {
NSLog(#"finished");
}];
}
}
when i press to button, view turns to black. Is there any way to do? What is my mistake?
Thank you for your answer and interest.
I found my question's answer.
if (tempThemeColor == 10) {
[self loadTheme];
[UIView transitionWithView:self.view
duration:1.0
options:UIViewAnimationOptionTransitionFlipFromLeft
animations:^{
} completion:^(BOOL finished) {
}];
}else{
[self loadTheme];
[UIView transitionWithView:self.view
duration:1.0
options:UIViewAnimationOptionTransitionFlipFromRight
animations:^{
} completion:^(BOOL finished) {
}];
}
Before doing animation try to change the window/super view of the view's color
if (self.view.superview) {
self.view.superview.backgroundColor = [UIColor whiteColor];
}
self.view.window.backgroundColor = [UIColor whiteColor];

Correct way to stack UIView animations and blocks?

I've only worked a bit with UIView animations and blocks, basically one step animations. I'd like to stack a few steps into a sequence. The code below seems to be working but I'm wondering if this is the right approach and/or if there are any issues/limitations with placing blocks within blocks.
Blocks seem great though the code formatting gets sort of unwieldy/unreadable.
CGRect newFrame = CGRectMake(0, 0, 500, 500);
UIView *flashView = [[UIView alloc] initWithFrame:newFrame];
flashView.tag = 999;
[flashView setBackgroundColor:[UIColor grayColor]];
[flashView setAlpha:0.f];
[self.view addSubview:flashView];
[UIView animateWithDuration:.2f
animations:^{
// STEP 1: FADE IN
[flashView setAlpha:1.f];
}
completion:^(BOOL finished){
[UIView animateWithDuration:.9f
animations:^{
// STEP 2: FADE OUT
[flashView setAlpha:0.f];
}
completion:^(BOOL finished){
// STEP 3: CLEAN UP
[flashView removeFromSuperview];
}
];
}];
What you're doing is correct. Sometimes the nesting can get ugly. One alternative for readability is to put each animation in its own method:
-(IBAction)someButtonPressed:(id)sender {
[self saveSomeData];
[self fadeInAndOut];
}
-(void)fadeInAndOut {
[UIView animateWithDuration:.2f
animations:^{
// STEP 1: FADE IN
[self.flashView setAlpha:1.f];
}
completion:[self fadeOut]
];
}
-(void (^)(BOOL))fadeOut {
return ^(BOOL finished) {
[UIView animateWithDuration:.9f
animations:^{
// STEP 2: FADE OUT
[self.flashView setAlpha:0.f];
}
completion:[self cleanUpFlashView]
];
};
}
-(void (^)(BOOL))cleanUpFlashView {
return ^(BOOL finished){
// STEP 3: CLEAN UP
[self.flashView removeFromSuperview];
};
}
That way isn't horrible if you're just nesting once with simple code. If you're going to do something more complex you might try animateWithDuration:delay:options:animations:completion:
using delay: as a way to link the animations. For example:
[UIView animateWithDuration:.2f delay:0
options:UIViewAnimationOptionCurveEaseIn|UIViewAnimationOptionAllowUserInteraction
animations:^{
// STEP 1: FADE IN
[flashView setAlpha:1.f];
}
completion:nil
];
[UIView animateWithDuration:.9f delay:.2f
options:UIViewAnimationOptionCurveEaseIn|UIViewAnimationOptionAllowUserInteraction
animations:^{
// STEP 2: FADE OUT
[flashView setAlpha:0.f];
}
completion:^(BOOL finished){
// STEP 3: CLEAN UP
[flashView removeFromSuperview];
}
];

Resources