When i upload to app store, i have this problems
non-public classes: NSCalendarDate, NSTask
But i only use NSTimer to make my own stopwatch
This i my source code
self.timer = [NSTimer scheduledTimerWithTimeInterval:1
target:self
selector:#selector(stopWatch)
userInfo:nil
repeats:YES] ;
My "Pause" method
pauseStart = [NSDate dateWithTimeIntervalSinceNow:0];
previousFireDate = [self.timer fireDate];
[self.timer setFireDate:[NSDate distantFuture]];
My "Resume" method
float pauseTime = -1*[pauseStart timeIntervalSinceNow];
[self.timer setFireDate:[NSDate dateWithTimeInterval:pauseTime sinceDate:previousFireDate]];
i also have NSTimer in my AppDelegate
AppDelegate* appDelegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
appDelegate.delayTimer = [NSTimer scheduledTimerWithTimeInterval:1
target:self
selector:#selector(stopWatch)
userInfo:nil
repeats:YES];
I run in ios6
Could you please show me the root cause?
Thanks you so much
I must to remove mogenerator (https://github.com/rentzsch/mogenerator) library to resolve this problems
I don't know why this project use those private APIs
Related
The ProgressView is not updating while playing the song. By reading from other post i have used an update method to update at each time interval.
- (void)viewDidLoad {
[super viewDidLoad];
NSString *filePath = [[NSBundle mainBundle]pathForResource:#"Fix you_Coldplay" ofType:#"mp3" inDirectory:#"Coldplay"];
NSLog(#"%#",filePath);
NSURL *url = [NSURL fileURLWithPath:filePath];
NSLog(#"%#",url);
musicPlayer = [[AVAudioPlayer alloc]initWithContentsOfURL:url error:nil];
[musicPlayer prepareToPlay];
[trackProgress setProgress:0.0];
}
I have a play button which is also being used for calling updateTime: method.
- (IBAction)playButton:(id)sender {
[musicPlayer play];
[NSTimer scheduledTimerWithTimeInterval:0.0 target:self selector:#selector(updateTime:) userInfo:nil repeats:YES];
NSTimeInterval interval = musicPlayer.currentTime/musicPlayer.duration;
NSLog(#"%f",interval);
}
The updateTime: method
-(void)updateTime:(NSTimer *)timer {
trackProgress.progress = (musicPlayer.currentTime/musicPlayer.duration);
}
I am very new to programming and even stack overflow. This is the first question i am posting. Please help me and Thanks in advance.
First of all change timer value to:
//Change Value to 0.5 or 1 sec
[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:#selector(updateTime:) userInfo:nil repeats:YES];
Make sure you are setting trackProgress as 0 as initial value.
- (void)viewDidLoad {
[super viewDidLoad];
trackProgress.progress = 0.0;
}
Hope this will resolve your issue.
Make sure to update the progress view on the main thread
-(void)updateTime:(NSTimer *)timer {
dispatch_async(dispatch_get_main_queue(), ^{
self.trackProgress.progress = (musicPlayer.currentTime/musicPlayer.duration);
});
}
This might help. Create a Timer and add it to common runloop as shown below. Also keep a reference to timer so that it can be stopped later.
self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(updateTime:) userInfo:nil repeats:YES];
[[NSRunLoop mainRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
I create a NSTimer:
timer = [NSTimer scheduledTimerWithTimeInterval:0.1f target:self selector:#selector(sendImage) userInfo:nil repeats:YES];
In the method sendImage, I create another NSTimer timer2. The code following:
- (void)sendImage
{
for(int i = 0;i < 50 ; i++)
{
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
[dict setObject:socket forKey:#"socket"];//parameter which deliver to the method`sendPieceOfImage`
[dict setObject:pData forKey:#"pData"];
timer2 = [NSTimer scheduledTimerWithTimeInterval:0.002f target:self selector:#selector(sendPieceOfImage:) userInfo:dict repeats:NO];
}
}
But it didn't work. I want to know can NSTimer apply mechanically? If it's infeasible, what can I do in the sendImage. I hope every cycle in the for() can run with interval.
The answer to your question is YES. That's possible to schedule one timer in the firing callback of another. Consider this:
dispatch_async(dispatch_get_main_queue(), ^{
[NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(timer1Event:) userInfo:nil repeats:YES];
});
- (void)timer1Event:(NSTimer*)timer {
NSLog(#"timer1Event");
[NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(timer2Event:) userInfo:nil repeats:NO];
}
- (void)timer2Event:(NSTimer*)timer {
NSLog(#"timer2Event");
}
Even the problem is not fully described, I'll try to guess that the rootcause is in how very first timer is scheduled.
You need thread with aproprietaly setted up RunLoop. Main thread is suitable.
dispatch_async(dispatch_get_main_queue(), ^{
self.timer = [NSTimer scheduledTimerWithTimeInterval:0.1f target:self selector:#selector(sendImage) userInfo:nil repeats:YES];
});
If you don't want to load the main thread, consider this:
You need your own thread:
self.workerThread = [[NSThread alloc] initWithTarget:self selector:#selector(startRunLoop) object:nil];
[self.workerThread start];
Which starts the runloop:
- (void)startRunLoop
{
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
[runLoop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];
do {
#autoreleasepool
{
[runLoop runUntilDate:[NSDate dateWithTimeIntervalSinceNow:2.0]];
}
} while (![NSThread currentThread].isCancelled);
}
Now, for starting the timer on the worker thread you need this:
- (void)startTimer
{
self.timer = [NSTimer scheduledTimerWithTimeInterval:10 target:self selector:#selector(timerEvent:) userInfo:nil repeats:YES];
}
How to call:
[self performSelector:#selector(startTimer) onThread:self.workerThread withObject:nil waitUntilDone:NO];
Hope it helps.
I have UIView with button Start, UILabel with my NSTimer time and UITableView with time record.
Problem is when I scroll my tableview - NSTimer freeze, why I can do to they work async?
My code:
- (IBAction)startTimer {
_startButton.hidden = YES;
_stopButton.hidden = NO;
isRun = YES;
UIBackgroundTaskIdentifier bgTask = UIBackgroundTaskInvalid;
UIApplication *app = [UIApplication sharedApplication];
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
[app endBackgroundTask:bgTask];
}];
myTimer = [NSTimer scheduledTimerWithTimeInterval:0.01f
target:self
selector:#selector(tick)
userInfo:nil
repeats:YES];
}
- (void)tick {
_timeSot++;
sot++;
/*some code*/
myTime = [NSString stringWithFormat:#"%#:%#:%#", minStr, secStr, sotStr];
[_timeLabel setText:myTime];
}
Add myTimer to NSRunLoopCommonModes:
myTimer = [NSTimer scheduledTimerWithTimeInterval:0.01f
target:self
selector:#selector(tick)
userInfo:nil
repeats:YES];
[[NSRunLoop mainRunLoop] addTimer:myTimer forMode:NSRunLoopCommonModes];
I previously had a single NSTimer which is working fine. I have added another NSTimer to my runloop as now I need to call two functions repeatedly after a delay. Both functions have a different delay. My code is given below.
self.now = [NSDate date] ;
self.timer = [[NSTimer alloc] initWithFireDate:self.now
interval:500
target:self
selector:#selector(Func1)
userInfo:nil
repeats:YES] ;
self.runLoop = [NSRunLoop currentRunLoop];
[runLoop addTimer:self.timer forMode:NSDefaultRunLoopMode];
[self.runLoop runUntilDate:[NSDate dateWithTimeIntervalSinceNow:10000]];
//Second timer start here.its not working.The function 'func2' is not getting called
self.now = [NSDate date] ;
self.timer = [[NSTimer alloc] initWithFireDate:self.now
interval:60
target:self
selector:#selector(Func2)
userInfo:nil
repeats:YES] ;
self.runLoop = [NSRunLoop currentRunLoop];
[runLoop addTimer:self.timer forMode:NSDefaultRunLoopMode];
[self.runLoop runUntilDate:[NSDate dateWithTimeIntervalSinceNow:10000]];
The first NSTimer is still working but the second NSTimer doesn't work.
While it's not good that you're overwriting your properties (it doesn't affect the timers' ability to run, individually, but it just means that you're discarding your reference to the first timer when you set the second timer, and thus you lose the ability to invalidate the first timer, should you ever need to do that), the key problem is that you're calling runUntilDate. There's no need to do that and the first runUntilDate is preventing the creation of the second timer from taking place as viewDidLoad will not proceed beyond the first runUntilDate call.
So remove both calls to runUntilDate and both timers will work fine. Use different properties to save the reference to the two timers if you want to keep a reference to both so that you can individually invalidate them if and when you no longer need them. (And it's important that you invalidate them when you no longer need them because they maintain a strong reference to self, which means that you have a "strong reference cycle".)
You could simplify the code sample:
NSDate *date = [NSDate date];
self.timer1 = [[NSTimer alloc] initWithFireDate:date
interval:500
target:self
selector:#selector(method1:)
userInfo:nil
repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:self.timer1 forMode:NSRunLoopCommonModes];
self.timer2 = [[NSTimer alloc] initWithFireDate:date
interval:60
target:self
selector:#selector(method2:)
userInfo:nil
repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:self.timer2 forMode:NSRunLoopCommonModes];
Or, unless you really need NSRunLoopCommonModes, you could just do:
self.timer1 = [NSTimer scheduledTimerWithTimeInterval:500
target:self
selector:#selector(method1:)
userInfo:nil
repeats:YES];
self.timer2 = [NSTimer scheduledTimerWithTimeInterval:60
target:self
selector:#selector(method2:)
userInfo:nil
repeats:YES];
And note, I'm using methods with a parameter (hence the colon with the selector):
- (void)method1:(NSTimer *)timer
{
// do whatever
}
- (void)method2:(NSTimer *)timer
{
// do whatever
}
You have to declare a second property of NSTimer. Currently you are overwriting your first timer when doing this
self.timer = [[NSTimer alloc] initWithFireDate:self.now
interval:60
target:self
selector:#selector(Func2)
userInfo:nil
repeats:YES] ;
Declare timer2 in your interface analogues to your timer declaration and the use self.timer2 to store the second timer.
Actually the runUntilDate will cause the app to keep on running the timer and the statements after this will not be executed. Try this:
self.now = [NSDate date] ;
self.timer = [[NSTimer alloc] initWithFireDate:self.now
interval:500
target:self
selector:#selector(Func1)
userInfo:nil
repeats:YES] ;
self.runLoop = [NSRunLoop currentRunLoop];
[runLoop addTimer:self.timer forMode:NSDefaultRunLoopMode];
//Second timer start here.its not working.The function 'func2' is not getting called
self.now = [NSDate date] ;
self.timer = [[NSTimer alloc] initWithFireDate:self.now
interval:60
target:self
selector:#selector(Func2)
userInfo:nil
repeats:YES] ;
self.runLoop = [NSRunLoop currentRunLoop];
[runLoop addTimer:self.timer forMode:NSDefaultRunLoopMode];
Even if you use the same timer variable for both timers, it will work. But as pointed out in other answers, you lose the ability to invalidate the first timer. Just comment out the runUntilDate statements in both places.
Declare a second property for your timers is not the solution. You just have to invalidate the old timer and allocate the new one on main thread and it will works! try this:
dispatch_async(dispatch_get_main_queue(), ^{
_timer = [NSTimer scheduledTimerWithTimeInterval:interval
target:self
selector:#selector(function:)
userInfo:nil
repeats:YES];
[_timer fire];
});
Is there a way to send a parameter to the selector via a NSTimer ?
myTimer =[NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(removeTheNote:) userInfo:nil repeats:NO];
- (void)removeTheNote:(NSString*)note
{
NSLog(#"Note %# ----------- REMOVED!",note);
}
I know that using :
myTimer =[NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(removeTheNote:myNote) userInfo:nil repeats:NO];
doesn't work, so I am asking, is there a way to do this?
You can use the userInfo parameter for that:
myTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(removeTheNote:) userInfo:myNote repeats:NO];
But you will have to modify removeTheNote as follows:
- (void)removeTheNote:(NSTimer *)timer
{
NSString *note = timer.userInfo;
NSLog(#"%#", note);
}