I am trying to implement method that affect UILabel text each every 1 seconds , It is going to be a reminder text like " You can skip ad in 5,4,3,2,1 skip now >>"
My method works fine except in 2nd and 3rd seconds timer call method like a more than 1 times each on second. I am using UIApplication sharedapplication.keywindows for present UI over full screen MPMoviePlayerController . Here is my method :
-(void)closeButtonForVideoPlayer
{
myButton = [[UIButton alloc] initWithFrame:CGRectMake(self.view.frame.size.width-30, 12, 25, 25)];
window = [UIApplication sharedApplication].keyWindow;
if (!window)
{
window = [[UIApplication sharedApplication].windows objectAtIndex:0];
}
[myButton addTarget:self action:#selector(videoFinished:) forControlEvents:UIControlEventTouchUpInside];
[myButton setImage:self.closeButton forState:UIControlStateNormal];
labelReminder = [[UILabel alloc] initWithFrame:CGRectMake(self.view.frame.size.width-130, 12, 130, 35)];
labelReminder.textColor = [UIColor whiteColor];
labelReminder.backgroundColor = [UIColor blackColor];
self.timderReminder = [NSTimer scheduledTimerWithTimeInterval:1.0
target: self
selector:#selector(reminderForVideoPlayer:)
userInfo: #{#"boolType":#"YES"} repeats:NO];
}
The reminder method :
-(void)reminderForVideoPlayer:(NSTimer *)userInfo
{
NSString *isVideoAdvertisement = [userInfo.userInfo objectForKey:#"boolType"];
NSLog(#"NSTimer info = %#",userInfo.userInfo);
if([isVideoAdvertisement isEqualToString:#"YES"])
{
if(remind >= 5)
{
[self.timderReminder invalidate];
remind = 0;
NSLog(#"reklam geçildi window");
[labelReminder removeFromSuperview];
labelReminder = nil;
[labelReminder setHidden:YES];
[window addSubview:myButton];
} else {
[window addSubview:labelReminder];
[labelReminder setText:[NSString stringWithFormat:#"Reklami geç: %d",5-remind]];
NSLog(#"reminder window = %d",remind);
remind ++;
self.timderReminder = [NSTimer scheduledTimerWithTimeInterval:1.0
target: self
selector:#selector(reminderForVideoPlayer:)
userInfo: #{#"boolType":#"YES"} repeats:NO];
}
}
Which part i am making mistake ? and how i can fix that issue ?
Best Regards,
Onder OZCAN
Try this control it will fulfil your requirements
https://github.com/mineschan/MZTimerLabel
in viewDidLoad
self.timderReminder = [NSTimer scheduledTimerWithTimeInterval:1.0
target: self
selector:#selector(reminderForVideoPlayer:)
userInfo: #{#"boolType":#"YES"} repeats:YES];
and
-(void)reminderForVideoPlayer:(NSTimer *)userInfo
{
NSString *isVideoAdvertisement = [userInfo.userInfo objectForKey:#"boolType"];
NSLog(#"NSTimer info = %#",userInfo.userInfo);
if([isVideoAdvertisement isEqualToString:#"YES"])
{
if(remind < 5)
{
[labelReminder setText:[NSString stringWithFormat:#"Reklami geç: %d",5-remind]];
NSLog(#"reminder window = %d",remind);
[labelReminder setHidden:NO];
} else {
[labelReminder setHidden:YES];
// [window addSubview:myButton]; //add this button in view did load only over here use setHidden method
[myButton setHidden: NO];
}
}
Try with this code.
Change the repeats parameter of NSTimer to YES. And you won't have to create a timer again each time it's fired. When your counter reaches to 5, just invalidate your timer.
Related
This is my code , i have added NStimer
PDColoredProgressView *progressVIew =[[PDColoredProgressView alloc] initWithProgressViewStyle:UIProgressViewStyleDefault];
[progressVIew setFrame:CGRectMake(50, 50, 200, 25)];
[progressVIew setProgress:0.1 animated:YES];
[ progressVIew setTintColor:[UIColor redColor]];
[self.view addSubview:progressVIew];
- (IBAction)startCount:(id)sender
{
_progressVaalue = 0.0f
self.myTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(updateUI:) userInfo:nil repeats:YES];
}
- (void)updateUI:(NSTimer *)timer
{
int count =0; count++;
if (count <= 1)
{
_progressVaalue = _progressVaalue + 0.1;
progressVIew.progress = _progressVaalue;
}
I am getting like this
This is my code, the progressive view not Showing
I am using NSTimer and circular progress bar for the countdown timer i.e 15seconds
Its working with the following code but I am getting tick animation for the progress bar and not the smooth one, how to make it smooth animation
- (void)viewDidLoad
{
[super viewDidLoad];
self.labeledLargeProgressView.roundedCorners = NO;
self.labeledLargeProgressView.trackTintColor =[UIColor colorWithRed:0.0f/255.0f green:173.0f/255.0f blue:255.0f/255.0f alpha:1.0f];
self.labeledLargeProgressView.progressTintColor =[UIColor colorWithRed:255.0f/255.0f green:96.0f/255.0f blue:88.0f/255.0f alpha:1.0f];
self.labeledLargeProgressView.thicknessRatio = 1.0f;
self.labeledLargeProgressView.clockwiseProgress = YES;
[self.view addSubview:self.labeledLargeProgressView];
seconds = 15.0;
[self startAnimation];
}
- (void)progressChange
{
CGFloat progress ;
DALabeledCircularProgressView *labeledProgressView = self.labeledLargeProgressView;
if(labeledProgressView.progress >=1.0f && [self.timer isValid]){
[self stopAnimation];
seconds = 15.0f;
}
else{
progress=labeledProgressView.progress + 0.06666667f;
[labeledProgressView setProgress:progress animated:YES];
seconds --;
labeledProgressView.progressLabel.text = [NSString stringWithFormat:#"%i", seconds];
}
}
- (void)startAnimation
{
self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:#selector(progressChange)
userInfo:nil
repeats:YES];
self.continuousSwitch.on = YES;
}
- (void)stopAnimation
{
[self.timer invalidate];
self.timer = nil;
self.continuousSwitch.on = NO;
}
What i found out is a set of both UIview animations and progress view animatons that work much nicer and animate the progressview smoothly. If you just use the combination of animation and progressview animation it is fired directly without regard to the UIview animation timer.
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
timer = [NSTimer scheduledTimerWithTimeInterval: 1.0f
target: self
selector: #selector(updateTimer)
userInfo: nil
repeats: YES];
}
- (void)updateTimer
{
if (progressView.progress >= 1.0) {
[timer invalidate];
}
[UIView animateWithDuration:1 animations:^{
float newProgress = [self.progressView progress] + 0.125;
[self.progressView setProgress:newProgress animated:YES];
}];
}
Feel free to adjust the animation times to even better and smooth transitions
I solved it by myself what I did is I am updating more frequently 0.1f instead of 1.0f
- (void)progressChange
{
CGFloat progress ;
DALabeledCircularProgressView *labeledProgressView = self.labeledLargeProgressView;
if(labeledProgressView.progress >=1.0f && [self.timer isValid]){
[self stopAnimation];
seconds = 15.0f;
_counter = 0;
}
else{
progress=labeledProgressView.progress + 0.00666667f;
_counter ++;
[labeledProgressView setProgress:progress animated:YES];
if(_counter % 10 == 0){
seconds --;
}
labeledProgressView.progressLabel.text = [NSString stringWithFormat:#"%i", seconds];
}
}
- (void)startAnimation
{
self.timer = [NSTimer scheduledTimerWithTimeInterval:0.1
target:self
selector:#selector(progressChange)
userInfo:nil
repeats:YES];
self.continuousSwitch.on = YES;
}
I am working on a kids app and need to make the answer disappear after a few seconds.
What do I need to add?
- (IBAction)calculate2:(id)sender
{
float aaaa = 6;
Answer2.text = [ [NSString alloc] initWithFormat:#"%.0f ",aaaa];
}
Use NSTimer and mention the specified time for UILabel to disappear:
- (IBAction)calculate2:(id)sender
{
float aaaa = 6;
Answer2.text = [[NSString alloc] initWithFormat:#"%.0f ",aaaa];
[NSTimer scheduledTimerWithTimeInterval:2.0
target:self
selector:#selector(targetMethod:)
userInfo:nil
repeats:NO];
}
-(void)targetMethod:(NSTimer*)timer
{
//toggle hidden parameter
[Answer2 setHidden:!Answer2.hidden];
}
-(void) hideLabel
{
[Answer2 setHidden:YES];
}
just add [self performSelector:#selector(hideLabel) withObject:nil afterDelay:4] to calculate2
For hiding it non-animated it will be:
[label setHidden:YES];
But if you want to hide it with an Animation it could be:
[UIView animatedwithduration:1.0f delay:.35f animations:{
label.alpha = 0.0;
}completion:{
[label removeFromSuperview];
//Here you can put a completed code
}];
Hope it helps!
I'm working on creating a timer, which is in the format of HH:mm, but my issue right now is pausing the timer and resuming it. Right now, when you pause the timer, it continues to count in the background, but the visible portion has stopped. Once you click on the resume button, the timer updates to where it left off, which, pending how long you it had been paused, could be any number above what it should be.
For instance, if the timer counted to 5, you then pause the timer, which now is sitting at 5, once you click resume, the timer may start at 15 since it had been 10 seconds since you paused it. Below is my code, which I have combined from several places to get this working:
- (void) createTimerPage
{
_dateFormat = [NSDate date];
// Add pause button
UIImage *pause = [UIImage imageNamed:#"pause.png"];
_pauseBtn = [UIButton buttonWithType:UIButtonTypeCustom];
_pauseBtn.frame = CGRectMake(151, 17, 32, 32);
[_pauseBtn addTarget:self action:#selector(pauseTimer) forControlEvents:UIControlEventTouchUpInside];
[_pauseBtn setBackgroundImage:pause forState:UIControlStateNormal];
}
- (void) startTimer
{
// Start timer
NSInteger secondsSinceStart = (NSInteger) [[NSDate date] timeIntervalSinceDate:_dateFormat];
NSInteger seconds = secondsSinceStart % 60;
NSInteger minutes = (secondsSinceStart / 60) % 60;
NSString *result = nil;
result = [NSString stringWithFormat:#"%02d:%02d", minutes, seconds];
_timerText.text = result;
[_timerBtns addSubview:_pauseBtn];
}
- (void) startPressed
{
[_time invalidate];
_time = [NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:#selector(startTimer)
userInfo:nil
repeats:YES];
}
- (void) pauseTimer
{
if (_time) {
// pause timer
[_time invalidate];
[_timerBtns addSubview:_playBtn];
}
}
I suspect the problem is that you are storing the "start time" in the variable called "_dateFormat". That variable only gets set when createTimerPage is called so, of course, when you later attempt to determine the secondsSinceStart in startTimer, it is still computing the time since createTimerPage was called.
Honestly, for what you are trying to do, I would not worry about a start time at all. Instead, I would just use a counter of the number of times the timer method gets called. I would also rename some of your methods to make it clearer what is actually going on. For example, your "startTimer" method isn't actually starting a timer. It's what gets called when your one second timer fires.
Finally, one other issue is that you are constantly adding subviews but, at least with the code posted, never removing them. You could (should) remove the unused subview every time you add a new one. Honestly, though, you would be better off leaving both views as part of your view hierarchy and using the hidden attribute to only show one of them.
Something like this will do what you want:
NSUInteger _timerSeconds;
NSTimer * _timer;
- (void) createTimerPage
{
// Add pause button
UIImage *pause = [UIImage imageNamed:#"pause.png"];
_pauseBtn = [UIButton buttonWithType:UIButtonTypeCustom];
_pauseBtn.frame = CGRectMake(151, 17, 32, 32);
[_pauseBtn addTarget:self action:#selector(pausePressed) forControlEvents:UIControlEventTouchUpInside];
[_pauseBtn setBackgroundImage:pause forState:UIControlStateNormal];
[_timerBtns addSubview:_pauseBtn];
}
- (void) timerFired
{
_timerSeconds++;
NSInteger seconds = _timerSeconds % 60;
NSInteger minutes = (_timerSeconds / 60) % 60;
NSString * result = [NSString stringWithFormat:#"%02d:%02d", minutes, seconds];
_timerText.text = result;
}
- (void) startPressed
{
// start timer
_timer = [NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:#selector(timerFired)
userInfo:nil
repeats:YES];
_playBtn.hidden = YES;
_pauseBtn.hidden = NO;
}
- (void) pausePressed
{
if (_timer) {
// pause timer
[_timer invalidate];
_playBtn.hidden = NO;
_pauseBtn.hidden = YES;
}
}
I was actually able to figure this one out with some more research on the matter. I found a great example that helped me come up with the following:
- (IBAction)startRepeatingTimer:(id)sender
{
// Show feed text while timer is going
_feeding = [[UILabel alloc] initWithFrame:CGRectMake(92, 25, 100, 50)];
_feeding.text = #"FEEDING";
_feeding.textColor = [UIColor colorWithRed:1 green:1 blue:1 alpha:1];
if (_feeding) {
_feeding.hidden = NO;
}
[_timerArea addSubview:_feeding];
// Cancel preexisting timer
[_repeatingTimer invalidate];
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:#selector(timerTicked:)
userInfo:nil repeats:YES];
_repeatingTimer = timer;
if (_playBtn.hidden == NO) {
_playBtn.hidden = YES;
_pauseBtn.hidden = NO;
}
if (_bWindow.frame.origin.y == 0) {
[UIView animateWithDuration:0.3
animations:^ {
_bWindow.frame = CGRectMake(0, 0, self.view.frame.size.width, 203);
_bWindow.frame = CGRectMake(0, -130, self.view.frame.size.width, 203);
}];
}
[_timerBtns addSubview:_pauseBtn];
}
- (void) timerTicked:(NSTimer *)timer
{
_currentTimeInSeconds++;
_timerText.text = [self targetMethod:_currentTimeInSeconds];
}
- (IBAction)resetTimer:(id)sender
{
_feeding.hidden = YES;
if (_repeatingTimer) {
[_repeatingTimer invalidate];
}
if (_playBtn.hidden == YES) {
_playBtn.hidden = NO;
_pauseBtn.hidden = YES;
}
_currentTimeInSeconds = 0;
_timerText.text = [self targetMethod:_currentTimeInSeconds];
if (_bothBtn.hidden == YES) {
_bothBtn.hidden = NO;
_switchBView.hidden = YES;
}
if (_rightBtn.hidden == YES) {
_rightBtn.hidden = NO;
_switchRView.hidden = YES;
}
if (_leftBtn.hidden == YES) {
_leftBtn.hidden = NO;
_switchLView.hidden = YES;
}
}
- (IBAction)pauseRepeatingTimer:(id)sender
{
[_repeatingTimer invalidate];
if (_playBtn.hidden == YES) {
_playBtn.hidden = NO;
_pauseBtn.hidden = YES;
}
}
- (NSString *) targetMethod:(int)totalSeconds
{
//NSInteger secondsSinceStart = (NSInteger) [[NSDate date] timeIntervalSinceDate:_dateFormat];
int seconds = totalSeconds % 60;
int minutes = (totalSeconds / 60) % 60;
return [NSString stringWithFormat:#"%02d:%02d", minutes, seconds];
}
So here's my code :
- (IBAction)run:(id)sender {
animationPointer = 0;
self.animationArray = [[NSMutableArray alloc] init];
UIView *allViews = [[UIView alloc]
initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
for (int i = 0; i < [self.paths count]; i++) {
[allViews addSubview:[self createAnimation:[self.paths objectAtIndex:i]]];
[self.animationArray addObject:allViews];
}
timer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:#selector(animateTurn)
userInfo:nil repeats:YES];
}
- (void)animateTurn {
UIView *tempView = [self.animationArray objectAtIndex:animationPointer];
[self.view addSubview:tempView];
for (UIImageView *view in tempView.subviews) {
[[tempView.subviews objectAtIndex:animationPointer] startAnimating];
}
animationPointer++;
if (animationPointer >= [self.animationArray count]) {
[timer invalidate];
}
}
createAnimation returns, as you would expect, a fully animated UIImageView. The plan is to have several on each UIView and then animate them all on a UIView then the next after half a second and it repeats. There's only one on each UIView for now.
However, when calling animateTurn on the NSTimer, the animations don't show up.
If I call the method via the normal [self animateTurn] then they appear but nothing with NSTimer nor the performSelector function.
Any help with this (or even suggestions for a better method)?
EDIT:
I should mention the function is actually being triggered and the code is being run including the startAnimating (checked with BOOL/NSLog). There is simply nothing being shown.
This is Your Solution:-
This is what I used and now the selector is Working. :-)
if (![NSThread isMainThread])
{ [self performSelectorOnMainThread:#selector(selectorToRunInMainThread) withObject:nil waitUntilDone:NO];
}
-(void)selectorToRunInMainThread
{
NSString *str = #"Timer event has fired";
NSTimer *atimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(updateModel:) userInfo:str repeats:YES];
}
Include this line after your timer:-
[timer fire];