How to stop and start app delegate timer using objective c? - ios

I have in my app login and logout process here I am facing so many problem with background timer services process. Below code I am maintaining for notification and JSON service background while applicationDidBecomeActive.
-(void)applicationDidBecomeActive:(UIApplication *)application
{
checkJSONtimer = [NSTimer scheduledTimerWithTimeInterval:300 target:self selector:#selector(updateJSON) userInfo:nil repeats:TRUE];
NSLog(#"%s", __PRETTY_FUNCTION__);
application.applicationIconBadgeNumber = 0;
}
Problems below
Before login, timer activity started
After logout, timer activity not stopping
If I commented above timer after background to come active state,
then timer not working
Every time without logout , cleared background app running again
open I can go from login
FYI : Above timer selector method I am maintaining below three places
1. application didFinishLaunchingWithOptions
2. applicationDidBecomeActive
3. applicationDidEnterBackground
How to solve above problems. Please help me!

Before login, timer activity started
For that you have to make a check whether the user is log-in the app or not.For example
-(void)applicationDidBecomeActive:(UIApplication *)application{
if(isUserLogedIn) {
checkJSONtimer = [NSTimer scheduledTimerWithTimeInterval:300 target:self selector:#selector(updateJSON) userInfo:nil repeats:TRUE];
NSLog(#"%s", __PRETTY_FUNCTION__);
application.applicationIconBadgeNumber = 0;
}
}
After logout, timer activity not stopping
For that, make a Notification which will trigger when the user log-out from the app.When the notification triggers the invalidate the timer.[myTimer inValidate].
If I commented above timer after background to come active state, then timer not working
No need to comment the timer.Just manage the timer affectively.
Every time without logout , cleared background app running again open I can go from login.
For that you have to manage the User session in NSUserDefaults.Check the value, if the value is not null, the log-in user automatically.

If you want to cancel the timer you can use something like this:
AppDelegate* appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
[appDelegate.checkJSONtimer invalidate]

Related

Unable to print out logs when app goes to background in test device

I am trying to implement certain app feature when app goes to background. But i saw a strange issue that if i do NSLog after every 2 seconds using NSTimer in "applicationDidEnterBackground", using simulator it works, but when i tested it in actual device, it doesn't print. Below is my code from "AppDelegate.m":
- (void)printLog
{
NSLog(#"logging after 2 sec.");
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
bckTimer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:#selector(printLog) userInfo:nil repeats:YES];
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
[bckTimer invalidate];
}
Please let me know why it's happening like this and may be any tips you would like to share while working with background app feature execution.
Thanks

listen server in applicationDidEnterBackground

I have a messaging application and I want that the application listens the server on background and when new message comes, fires notification.
I tried to do that with timers and backgroundtasks, i can listen the server and the application fires the notification but when i reopen the application, i can not interact with anything, like the application is locked. Can you suggest any proper way to do that?
- (void)applicationDidEnterBackground:(UIApplication *)application
{
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(sbCheckServerRecords) name:#"UIApplicationDidEnterBackgroundNotification" object:nil];
}
-(void) sbCheckServerRecords{
self.tmrCheckRecords = [[NSTimer alloc] initWithFireDate:[NSDate dateWithTimeIntervalSinceNow:1] interval:10.0 target:self selector:#selector(sbCheckRecords) userInfo:nil repeats:YES];
[self.tmrCheckRecords fire];
}
-(void) sbCheckRecords{
#try{
if(any message comes)
notify user;
}
}
I have used timer as dispatch_source_t and
this class worked for me:
https://gist.github.com/maicki/7622108

how to hit the service url everyday 7 am using NStimer in IOS?

- (NSTimer *) timer
{
(!_timer)
{
_timer = [NSTimer timerWithTimeInterval:86400 target:self selector:#selector(timeset:) userInfo:nil repeats:YES];
}
return _timer;
}
You can't schedule execution for a specific time in the background on iOS. You can schedule a UILocalNotification - but your app will only be launched if the user taps on the notification.
Your best bet is to use background fetch mode. You app will be woken at intervals and given an opportunity to fetch new data. You can check to see if the time is at or after 7 and decide whether to refresh the data.

How to re-trigger a process repeatedly in background in xcode

I'am working on an application in xcode-5, I need to upload some data in background mode, I need a set of code to be repeated till the device terminates the background process. I am able to do it once but I need to repeat again and again so that i can check the connectivity and perform the upload. I doing the same thing when the application comes in active mode.
Currently I'm using Timers with the following code :
- (void)applicationDidEnterBackground:(UIApplication *)application
{
[bgrdTimer_ActiveMode invalidate];
bgrdTimer_ActiveMode=nil;
self.backgroundTask=[application beginBackgroundTaskWithExpirationHandler:^{
self.backgroundTask=UIBackgroundTaskInvalid;
}];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),^{
bgrdTimer_BackGroundMode=[NSTimer scheduledTimerWithTimeInterval:40.00 target:self selector:#selector(repeatUploadProcess_BackGroundMode) userInfo:nil repeats:YES];
});
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
[bgrdTimer_BackGroundMode invalidate];
bgrdTimer_BackGroundMode=nil;
bgrdTimer_ActiveMode=[NSTimer scheduledTimerWithTimeInterval:40.00 target:self selector:#selector(repeatUploadProcess_ActiveMode) userInfo:nil repeats:YES];
}
repeatUploadProcess_ActiveMode and repeatUploadProcess_BackGroundMode are the methods containing the set of code which is suppose to be repeated
the problem is when I invalidate the bgrdTimer_ActiveMode the other timer dosn't gets invoked.
Have you enabled the background fetch mode? Click on the project target, and under the capabilities tab select "background fetch".
Theoretically you should also be setting [application endBackgroundTask:bgTask]. It sounds like you know, but if it never ends, iOS will end up killing your app.

iOS reading data from server regularly

I need to create a iOS app where the app has to continuously check for the updates from the server(may be every 30 secs). But only when the app is running on the foreground.
I know this will drain the battery, but this will run on a environment where there's no internet. So we can't use push notifications.
Only option I can think of is sending a request to the server every 30 secs or so and get the updates. What is the best way to do this? Using NSTimer and NSURLConnection or any other better approaches?
Also if I use a timer, when the app goes to the background will it pause and will it start running as it comes to the foreground again? Is there a chance that app get killed while its on background?
Thanks
Using NSTimer and NSURLConnection or any other better approaches?
My first thought was also to use NSTimer and NSURLConnection.
Also if I use a timer, when the app goes to the background will it pause and will it start running as it comes to the foreground again?
Yes, it will. It doesn't exactly pause, but based on my testing in the simulator, the effect is similar. Let's say the timer is set to go off at 00:00:00, 00:00:30, 00:00:60, ... and you background the app at 00:00:15 and resume it at 00:00:45. The timer that was supposed to fire at 00:00:30 fires immediately when you resume (at 00:00:45), and the next firing (at 00:00:60) and subsequent firings are back on schedule.
Is there a chance that app get killed while its on background?
Yes, there is. But if you start the timer whenever the app launches, this shouldn't be a problem, right?
Your best bet is to setup a separate object that manages these operations on a background thread. Then in your app delegate, when
- (void)applicationWillResignActive:(UIApplication *)application
is called, have this special object stop all of it's synchronizing and clean up anything it needs to.
Then when:
- (void)applicationDidBecomeActive:(UIApplication *)application
gets called as the app gets active again, signal your object to query / poll on its background thread again.
Your custom object could have an interface like this
#interface PollingObject : NSObject
{
NSTimer* _timer;
NSUinteger _interval;
BOOL _cancel;
BOOL _isPolling;
dispatch_queue_t _pollQueue;
}
- (void)startPolling;
- (void)stopPolling;
#end
The implementation can be something like this:
#implementation PollingObject : NSObject
- (id)init
{
if (self = [super init])
{
_interval = 1; // 1 second interval
_cancel = NO; // default to NO
_isPolling = NO; // default to NO
// init your background queue
_pollQueue = dispatch_queue_create("com.yourconame.yourappname.pollQueue", NULL);
}
return self;
}
- (void)heartbeat
{
if (_cancel)
{
// stop the timer
[_timer invalidate];
_isPolling = NO;
return;
}
// Runs the polling method ONCE on a background queue
dispatch_async(_pollQueue, ^{
[self pollingMethod];
});
}
- (void)pollingMethod
{
// Do actual network polling work here...but only run it once. (don't loop)
}
- (void)startPolling
{
_cancel = NO;
if (_isPolling)
{
NSLog(#"Already polling");
return;
}
// schedule the method heartbeat to run every second
_timer = [NSTimer scheduledTimerWithTimeInterval:_interval target:self selector:#selector(heartbeat) userInfo:nil repeats:YES];
}
- (void)stopPolling
{
// we set the flag here and the next second the heartbeat will stop the timer
_cancel = YES;
}
#end
Look at Rocket real-time networking which looks easy to setup through AFNetworking 2.0.
https://github.com/AFNetworking/AFNetworking/wiki/AFNetworking-2.0-Migration-Guide
See the last part of this wiki. I have not used it but it would be something I would try if I had your requirements.

Resources