PageViewController didFinishAnimating not called all the time - objective-c

PageViewController didFinishAnimating not called when swipe multiple time.
I have a function that recognize that user finish animation swipe and I start to move alone the page every 4 second.
sometimes didFinishAnimating not call in the last swipe.
-(void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed {
NSLog(#"\n\n\n didFinishAnimating \n\n\n");
_isAnimateWorking = NO;
if(completed){
_currentIndex = _nextIndex;
}
else
{
_currentProduct = prev_currentProduct;
_nextIndex = prev_nextIndex;
}
[self StartMoveAloneTimer];
}
-(void) StartMoveAloneTimer {
if (_myticker == nil) {
_myticker = [NSTimer scheduledTimerWithTimeInterval:4.0f target:self selector:#selector(GoToNextPage) userInfo:nil repeats:YES];
}
}

Related

Change NSTimer interval after a certain number of fires

In the following code, the NSTimer interval is set at 1 second between each picture. My goal is to change the interval after the first two pictures, hello.png and bye.png, to 4 seconds.
- (void)viewDidLoad {
[super viewDidLoad];
NSArray *imageNames = #[#"hello.png",#"bye.png",#"helloagain.png",#"bye again"];
self.images = [[NSMutableArray alloc] init];
for (int i = 0; i < imageNames.count; i++) {
[self.images addObject:[UIImage imageNamed:[imageNames objectAtIndex:i]]];
}
self.animationImageView = [[UIImageView alloc] initWithFrame:CGRectMake(60, 95, 86, 90)];
self.animationImageView.image = self.images[0];
[self.view addSubview:self.animationImageView];
self.animationImageView.userInteractionEnabled = TRUE;
[NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(changeImage:) userInfo:nil repeats:YES];
}
-(void)changeImage:(NSTimer *) timer {
if (counter == self.images.count - 1 ) {
counter = 0;
}else {
counter ++;
}
self.animationImageView.image = self.images[counter];
}
my goal is to change the interval
You cannot change a timer in any way. To change the firing interval, invalidate and destroy the timer and make a new timer with the new interval.
To do that, you will need to have kept a reference to the timer, as a property of your view controller (something that you have fatally failed to do in your implementation - you would have had no way to stop the timer, and you would have crashed if your view controller ever went out of existence, or else your view controller would have leaked because the timer retains it).
Make the timer object a member variable. Initially set animation time as 1 second. In the callback invalidate the timer and create a new one with 1 or 4 seconds depending on the counter.
#interface ViewController ()
#property (strong,nonatomic) NSMutableArray *images;
#property (strong,nonatomic) UIImageView *animationImageView;
{
NSTimer *_timer;
}
#end
#implementation ViewController {
NSInteger counter;
}
- (void)viewDidLoad {
[super viewDidLoad];
NSArray *imageNames = #[#"hello.png",#"bye.png",#"helloagain.png",#"bye again"];
self.images = [[NSMutableArray alloc] init];
for (int i = 0; i < imageNames.count; i++) {
[self.images addObject:[UIImage imageNamed:[imageNames objectAtIndex:i]]];
}
self.animationImageView = [[UIImageView alloc] initWithFrame:CGRectMake(60, 95, 86, 90)];
self.animationImageView.image = self.images[0];
[self.view addSubview:self.animationImageView];
self.animationImageView.userInteractionEnabled = TRUE;
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(bannerTapped:)];
singleTap.numberOfTapsRequired = 1;
singleTap.numberOfTouchesRequired = 1;
[self.animationImageView addGestureRecognizer:singleTap];
_timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(changeImage:) userInfo:nil repeats:YES];
}
-(void)changeImage:(NSTimer *) timer {
[_timer invalidate];
if (counter == self.images.count - 1 ) {
counter = 0;
}else {
counter ++;
}
if(counter == 0 || counter == 1)
{
_timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(changeImage:) userInfo:nil repeats:YES];
}
else if(counter == 2 || counter == 3)
{
_timer = [NSTimer scheduledTimerWithTimeInterval:4 target:self selector:#selector(changeImage:) userInfo:nil repeats:YES];
}
self.animationImageView.image = self.images[counter];
}
The best/simpliest way :
-(void)Timer{
// Do what you want here
// modify the frequency value if you want.
[NSTimer scheduledTimerWithTimeInterval:frequence target:self selector:#selector(Timer) userInfo:nil repeats:NO];
}
Frequence is a variable that contains the interval.
You just need to call Timer method by yourself the first time ;)
For you, it would give
-(void)changeImage{
if (counter == self.images.count - 1 )
counter = 0;
else
counter ++;
frequence = (counter < 2)?1:4;
self.animationImageView.image = self.images[counter];
[NSTimer scheduledTimerWithTimeInterval:frequence target:self selector:#selector(changeImage) userInfo:nil repeats:NO];
}

use of undeclared identifier in Xcode

I'm making an simple game, and Xcode finds a bug says that there is a "use of undeclared identifier 'gameLoop'". How can I fix this?
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
(void)viewDidLoad {
[super viewDidLoad];
gameState = kStateRunning;
[NSTimer scheduledTimerWithTimeInterval: 1.0/60 target:self selector:#selector(gameLoop) userInfo:nil repeats:YES];
rockVelocity = CGPointMake (0, 0);
gravity = CGPointMake (0, kGravity);
- (void)gameLoop {
if (gameState == kStateRunning)
{
[self gameStatePlayNormal];
}
else if (gameState == kStateGameOver)
{
}
}
(void)gameStatePlayNormal {
rockVelocity.y += gravity.y;
rock.center = CGPoint(rock.center.x + ballVelocity.x,rock.center.y + rockVelocity.y);
You need a closing bracket after your viewDidLoad method. Please note that methods in Objective C need a - or + in front of them.
-(void)viewDidLoad {
[super viewDidLoad];
gameState = kStateRunning;
[NSTimer scheduledTimerWithTimeInterval: 1.0/60 target:self selector:#selector(gameLoop) userInfo:nil repeats:YES];
rockVelocity = CGPointMake (0, 0);
gravity = CGPointMake (0, kGravity);
}
- (void)gameLoop {
if (gameState == kStateRunning)
{
[self gameStatePlayNormal];
}
else if (gameState == kStateGameOver)
{
}
}
-(void)gameStatePlayNormal {
rockVelocity.y += gravity.y;
rock.center = CGPoint(rock.center.x + ballVelocity.x,rock.center.y + rockVelocity.y);}

How can I produce a blinking label

I want a label to be shown for 0.4 seconds and then hidden for 0.8 seconds - in an infinite loop.
How can I pull that off?
NSTimer and UIViews hidden property would be one possibility
I would say to use NSTimer. You could do it the following way:
Say your label is myLabel:
#property (weak, nonatomic) IBOutlet UILabel *myLabel;
You should create a method to be called by NSTimer:
- (void)changeLabelState:(NSTimer *)timer
{
if(self.myLabel.hidden == TRUE)
{
self.myLabel.hidden = FALSE; //change comparassion to assing
[NSTimer scheduledTimerWithTimeInterval:0.4
target:self
selector:#selector(changeLabelState:)
userInfo:nil
repeats:NO];
}
else
{
self.myLabel.hidden = TRUE;
[NSTimer scheduledTimerWithTimeInterval:0.8
target:self
selector:#selector(changeLabelState:)
userInfo:nil
repeats:NO];
}
}
And initialize NSTimer somewhere like so:
[NSTimer scheduledTimerWithTimeInterval:0.4
target:self
selector:#selector(changeLabelState:)
userInfo:nil
repeats:NO];
Note that you could also do the following:
[self performSelector:#selector(changeLabelState:) withObject:nil afterDelay:0.4];
- (void)changeLabelState:(NSTimer *)timer
{
if(self.myLabel.hidden == TRUE)
{
self.myLabel.hidden = FALSE;
[self performSelector:#selector(changeLabelState:) withObject:nil afterDelay:0.4];
}
else
{
self.myLabel.hidden = TRUE;
[self performSelector:#selector(changeLabelState:) withObject:nil afterDelay:0.8];
}
}
Something Like the below.
In viewDidLoad:
NSTimer *silly = [NSTimer timerWithTimeInterval:0.4 target:self selector:#selector(question) userInfo:nil repeats:YES];
Function
-(void)question {
if(label.isHidden){
label.hidden = false;
} else {
label.hidden = true;
}
}
Make sure you have a UILabel defined in scope of this function and it should work. UNTESTED.

how to finish my countdown timer in objective c?

I have a countdown timer where the user can input the time they want to start from using a countdown timer like in the clock app. The problem is, I can't figure out how to make the timer actually count down. I have already made the UI and have most of the code, but I don't know what would go in the updateTimer method I have. Here is my code:
- (void)updateTimer
{
//I don't know what goes here to make the timer decrease...
}
- (IBAction)btnStartPressed:(id)sender {
pkrTime.hidden = YES; //this is the timer picker
btnStart.hidden = YES;
btnStop.hidden = NO;
// Create the timer that fires every 60 sec
stopWatchTimer = [NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:#selector(updateTimer)
userInfo:nil
repeats:YES];
}
- (IBAction)btnStopPressed:(id)sender {
pkrTime.hidden = NO;
btnStart.hidden = NO;
btnStop.hidden = YES;
}
Please let me know what goes in the updateTimer method to let the timer decrease.
Thanks in advance.
You would track the overall time left with a variable. The updateTimer method will be called every second, and you would reduce the time left variable by 1 (one second) each time updateTimer method is called. I have given an example below, but I have renamed updateTimer to reduceTimeLeft.
SomeClass.h
#import <UIKit/UIKit.h>
#interface SomeClass : NSObject {
int timeLeft;
}
#property (nonatomic, strong) NSTimer *timer;
#end
SomeClass.m
#import "SomeClass.h"
#implementation SomeClass
- (IBAction)btnStartPressed:(id)sender {
//Start countdown with 2 minutes on the clock.
timeLeft = 120;
pkrTime.hidden = YES;
btnStart.hidden = YES;
btnStop.hidden = NO;
//Fire this timer every second.
self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:#selector(reduceTimeLeft:)
userInfo:nil
repeats:YES];
}
- (void)reduceTimeLeft:(NSTimer *)timer {
//Countown timeleft by a second each time this function is called
timeLeft--;
//When timer ends stop timer, and hide stop buttons
if (timeLeft == 0) {
pkrTime.hidden = NO;
btnStart.hidden = NO;
btnStop.hidden = YES;
[self.timer invalidate];
}
NSLog(#"Time Left In Seconds: %i",timeLeft);
}
- (IBAction)btnStopPressed:(id)sender {
//Manually stop timer
pkrTime.hidden = NO;
btnStart.hidden = NO;
btnStop.hidden = YES;
[self.timer invalidate];
}
#end

NSTimer is Not stopping when double Click on a Button

I have NSTimer to display an image after 2 seconds when i click on button. It is working fine when I Click on a Button, But the problem is When I double Click the Button the NSTimer is Not Stopping. Continuously it is displaying images(calling NSTimer method) without Clicking on the button for Next Time. How to stop the NSTimer when i double Click / more Clicks on that button at a time.
*This is my Code*
-(void)buttonClicked
{
timer = [NSTimer scheduledTimerWithTimeInterval:0.2 target:self selector:#selector(timerClicked) userInfo:nil repeats:YES];
imgviewtransparent.image = [UIImage imageNamed:[imagesArray objectAtIndex:i]];
}
-(void)timerClicked
{
[timer invalidate];
timer = nil;
}
With double Click it will schedule timer twice.
You can create a BOOL property to avoid this if you want.
-(void)viewDidLoad{
[super viewDidLoad];
//Define all your implementation
//Set BOOL property to no at start
self.isButtonClicked = NO; // You need to define this BOOL property as well.
}
-(void)buttonClicked {
// Return if one click is already in process
if (self.isButtonClicked) {
return;
}
self.isButtonClicked = YES:
timer = [NSTimer scheduledTimerWithTimeInterval:0.2 target:self
selector:#selector(timerClicked) userInfo:nil repeats:YES];
imgviewtransparent.image = [UIImage imageNamed:[imagesArray objectAtIndex:i]];
}
-(void)timerClicked {
[timer invalidate];
timer = nil;
self.isButtonClicked = NO;
}