Running code in the background in IOS - ios

Firebase * ref = nil;
NSInteger iid = [[API sharedInstance] userid];
NSString * path = [NSString stringWithFormat: #"http://example.firebaseIO.com/user/%d/conversations", iid];
ref = [[Firebase alloc] initWithUrl:path];
if(ref) {
NSString * path = [NSString stringWithFormat: #"http://example.firebaseIO.com/conversations"];
Firebase * conv = [[Firebase alloc] initWithUrl: path];
[ref observeEventType:FEventTypeChildAdded withBlock:^(FDataSnapshot *snapshot) {
// name of conversation
NSString * name = snapshot.name;
Firebase * ref1 = [conv childByAppendingPath: name];
[ref1 observeSingleEventOfType:FEventTypeValue withBlock:^(FDataSnapshot *snapshot) {
if(snapshot.value != [NSNull null] && ![snapshot.value isKindOfClass: [NSString class]])
{
FDataSnapshot * chatsnapshot = [snapshot childSnapshotForPath: #"chats"];
NSInteger numChatMessages = chatsnapshot.childrenCount;
numberOfTotalChatMessages += numChatMessages;
NSMutableDictionary *m = [snapshot.value mutableCopy];
[m setValue: snapshot.name forKey: #"ref_name"];
NSInteger current_user = [[API sharedInstance] userid];
NSString * userpath = [NSString stringWithFormat: #"users/%d", current_user];
FDataSnapshot * usersnapshot = [snapshot childSnapshotForPath: userpath];
if(usersnapshot.value != [NSNull null] && ![usersnapshot.value isKindOfClass: [NSString class]])
{
NSDictionary * userdict = usersnapshot.value;
NSInteger numUserMessagesRead = [userdict[#"numOfMessages"] intValue];
numberOfMessagesRead += numUserMessagesRead;
if(numberOfTotalChatMessages > numberOfMessagesRead) {
[m setValue: #"true" forKey: #"bubble"];
}
}
[self.chats addObject: m];
NSNumber * index = [NSNumber numberWithInt: self.chats.count - 1];
[read setValue: index forKey: snapshot.name];
PLRightMenuViewController * rightPanel = (PLRightMenuViewController *) self.viewController.rightPanel;
[rightPanel.tableView reloadData];
self.numChats = numberOfTotalChatMessages - numberOfMessagesRead;
[[UIApplication sharedApplication] setApplicationIconBadgeNumber: self.numChats];
}
}];
}];
[ref observeEventType:FEventTypeChildChanged withBlock:^(FDataSnapshot *snapshot) {
NSString * name = snapshot.name;
Firebase * ref1 = [conv childByAppendingPath: name];
[ref1 observeSingleEventOfType:FEventTypeValue withBlock:^(FDataSnapshot *snapshot)
{
if(snapshot.value != [NSNull null] && ![snapshot.value isKindOfClass: [NSString class]])
{
numberOfTotalChatMessages += 1;
NSMutableDictionary *m = [snapshot.value mutableCopy];
[m setValue: snapshot.name forKey: #"ref_name"];
[m setValue: #"true" forKey: #"bubble"];
[self.chats addObject: m];
if([read objectForKey: snapshot.name])
{
NSInteger index = [[read objectForKey: snapshot.name] intValue];
[self.chats removeObjectAtIndex: index];
NSNumber * index1 = [NSNumber numberWithInt: self.chats.count - 1];
[read setValue: index1 forKey: snapshot.name];
}
self.numChats = numberOfTotalChatMessages - numberOfMessagesRead;
[[UIApplication sharedApplication] setApplicationIconBadgeNumber: self.numChats];
PLRightMenuViewController * rightPanel = (PLRightMenuViewController *) self.viewController.rightPanel;
[rightPanel.tableView reloadData];
}
}];
}];
}
I have the code above that basically checks for any new chat conversations using firebase and changes the application badge number. How can I run the code in the background of the app so that the application badge number is changed regardless of whether someone is currently using the app or not?
Basically, how can I run the code above in the background? What should I change in the Appdelegate?

You can't unless you cheat. Currently iOS or Apple respectively does not allow apps to go into the background with very few exceptions. Such as location services or playing audio.
Some cheat by pretending to play a sound or so.
Until now you would have to use push notifications in order to inform the app about incoming messages and update the badge.
Or ... wait for iOS 7 to be released. Assuming you've got a developer account, you can already access the docs and preview/beta resouces and prepare yourself until iOS 7 and the SDK etc. is GA.

// #interface
// Declare Private property
#property (nonatomic) UIBackgroundTaskIdentifier backgroundTask;
//#end
// ...
// Copy into
//#implementation
- (void)setupBackgrounding {
[[NSNotificationCenter defaultCenter] addObserver: self selector: #selector(appBackgrounding:)
name: UIApplicationDidEnterBackgroundNotification
object: nil];
[[NSNotificationCenter defaultCenter] addObserver: self selector: #selector(appForegrounding:)
name: UIApplicationWillEnterForegroundNotification
object: nil];
}
- (void)appBackgrounding: (NSNotification *)notification {
[self keepAlive];
}
- (void) keepAlive {
self.backgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
[[UIApplication sharedApplication] endBackgroundTask:self.backgroundTask];
self.backgroundTask = UIBackgroundTaskInvalid;
[self keepAlive];
}];
}
- (void)appForegrounding: (NSNotification *)notification {
if (self.backgroundTask != UIBackgroundTaskInvalid) {
[[UIApplication sharedApplication] endBackgroundTask:self.backgroundTask];
self.backgroundTask = UIBackgroundTaskInvalid;
}
}

You can do it with Push notification here is a great explanation about it.
example http://www.raywenderlich.com/32960/apple-push-notification-services-in-ios-6-tutorial-part-1
Note: you need one APNS which will notify your application.
In iOS7 come with feature with fetchAPI which will allow you to work on background but please note it not grantee that your application will run on background as system will decide when to allow application to run on background.
In iOS7 there is also one more thing call silent-Push notification which will allow you to update your view while notification come it means if your application in background and notification come you can change application badge number in background.

You need to use Apple Push Notification services, commonly abbreviated as APNs.

You can use these methods, to run background task for some more time..
- (UIBackgroundTaskIdentifier)beginBackgroundTaskWithExpirationHandler:(void(^)(void))handler NS_AVAILABLE_IOS(4_0);
- (void)endBackgroundTask:(UIBackgroundTaskIdentifier)identifier NS_AVAILABLE_IOS(4_0);
- (BOOL)setKeepAliveTimeout:(NSTimeInterval)timeout handler:(void(^)(void))keepAliveHandler NS_AVAILABLE_IOS(4_0);
- (void)clearKeepAliveTimeout NS_AVAILABLE_IOS(4_0);
- (void)getDataFromServer
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self beginBackgroundUpdateTask];
NSURLResponse * response = nil;
NSError * error = nil;
NSData * responseData = [NSURLConnection sendSynchronousRequest: request returningResponse: &response error: &error];
// Do something with the result
[self endBackgroundUpdateTask];
});
}
- (void) beginBackgroundUpdateTask
{
self.backgroundUpdateTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
[self endBackgroundUpdateTask];
}];
}
- (void) endBackgroundUpdateTask
{
[[UIApplication sharedApplication] endBackgroundTask: self.backgroundUpdateTask];
self.backgroundUpdateTask = UIBackgroundTaskInvalid;
}
Further more if you want to keep alive your application you can use this:-
- (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,
// called instead of applicationWillTerminate: when the user quits.
if ([application respondsToSelector:#selector(setKeepAliveTimeout:handler:)])
{
[application setKeepAliveTimeout:600 handler:^{
DDLogVerbose(#"KeepAliveHandler");
// Do other keep alive stuff here.
}];
}
}
It might help you..
And in iOS 7 there may be better ways to do that...

Related

Google place picker interrupts the background location updates in iPhone

I'm developing a location-based mobile application. My app updates the server with user's current location even when the app is killed/terminated. My app was working fine before integrating google place picker API. After installing google place picker API for ios, my app updates the location for about 5 to 10 minutes only and then it stops updating location.
//My code :
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Initialize Location Manager
sLocationManager;
//the system automatically relaunches the application into the background if a new event arrives.
// The options dictionary passed to the application:didFinishLaunchingWithOptions: method of your application delegate contains the key UIApplicationLaunchOptionsLocationKey to indicate that your application was launched because of a location event
if (launchOptions[UIApplicationLaunchOptionsLocationKey]) {
NSLog(#"---UIApplicationLaunchOptionsLocationKey");
sLocationManager.locationUpdatedInBackground = ^(NSArray<CLLocation *> *locations) {
NSLog(#"---setLocationUpdatedInBackground");
[sLocationModule saveNewLocations];
UILocalNotification *notification = [[UILocalNotification alloc] init];
notification.fireDate = [NSDate dateWithTimeIntervalSinceNow:300];
notification.alertBody = #"Your location was changed. Please run application for tracking your geoposition with best accuracy.";
[[UIApplication sharedApplication] scheduleLocalNotification:notification];
[sLocationManager startMonitoringSignificantLocationChanges];
};
}else {
sLocationManager.locationUpdatedInForeground = ^(NSArray<CLLocation *> *locations) {
NSLog(#"---setLocationUpdatedInForeground");
[sLocationModule saveNewLocations];
};
sLocationManager.locationUpdatedInBackground = ^(NSArray<CLLocation *> *locations) {
NSLog(#"---setLocationUpdatedInBackground");
[sLocationModule saveNewLocations];
[sLocationManager startDeferredLocationUpdates];
};
// Notifications
[application cancelAllLocalNotifications];
}
return YES;
//location manager
#pragma mark - CLLocationManager Delegate
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)aLocations {
NSString *infoMessage = [NSString stringWithFormat:#"%#", aLocations];
NSLog(#"%#", infoMessage);
locations = [#[] mutableCopy];
NSLog(#"locations=%#",locations);
[aLocations enumerateObjectsUsingBlock:^(CLLocation * _Nonnull location, NSUInteger idx, BOOL * _Nonnull stop) {
// Check for location errors (speed -1.00 mps / course -1.00)
// if (location.speed >= 0 &&
// location.course >= 0) {
if (locations.count > 0) {
if ([location.timestamp timeIntervalSinceDate:[locations lastObject].timestamp] > dLocationManagerDistanceFilter ||
[location distanceFromLocation:[locations lastObject]] > dLocationUpdatesUntilTimeout) {
[locations addObject:location];
NSLog(#"location.timestamp>dLocationManagerDistanceFilter**** locations=%#",locations);
}
} else
[locations addObject:location];
NSLog(#"else***locations=%#",locations);
//save location in userdefaults
NSString *latitudeValue = [NSString stringWithFormat:#"%f", location.coordinate.latitude];
NSString *longitudeValue = [NSString stringWithFormat:#"%f",location.coordinate.longitude];
NSLog(#"new location is recieved Lat : %# Long : %#",latitudeValue,longitudeValue);
[User setUserLat:latitudeValue];
[User setUserLon:longitudeValue];
// }
}];
if ([self isInBackground]) {
NSLog(#"app is in background***");
if (self.locationUpdatedInBackground) {
backgroundTaskIdentifier = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler: ^{
[[UIApplication sharedApplication] endBackgroundTask:backgroundTaskIdentifier];
}];
self.locationUpdatedInBackground(locations);
[delegate locationManagerDidUpdateLocationInBackground];
[[NSNotificationCenter defaultCenter] postNotificationName:nLocationManagerDidUpdateLocationInBackgroundNotification
object:nil
userInfo:nil];
[self endBackgroundTask];
}
} else {
if (self.locationUpdatedInForeground) {
if([[NSUserDefaults standardUserDefaults]objectForKey:#"userIdKey"]){
self.locationUpdatedInForeground(locations);
[delegate locationManagerDidUpdateLocationInForeground];
[[NSNotificationCenter defaultCenter] postNotificationName:nLocationManagerDidUpdateLocationInForegroundNotification
object:nil
userInfo:nil];
}
}
}
}
code for adding place picker
#pragma mark - Place picker delegate methods
- (IBAction)pickPlace:(id)sender {
//dismiss the keyboard
[tfLocation resignFirstResponder];
CLLocationCoordinate2D center = CLLocationCoordinate2DMake(locationManager.location.coordinate.latitude, locationManager.location.coordinate.longitude);
CLLocationCoordinate2D northEast = CLLocationCoordinate2DMake(center.latitude + 0.001, center.longitude + 0.001);
CLLocationCoordinate2D southWest = CLLocationCoordinate2DMake(center.latitude - 0.001, center.longitude - 0.001);
GMSCoordinateBounds *viewport = [[GMSCoordinateBounds alloc] initWithCoordinate:northEast
coordinate:southWest];
GMSPlacePickerConfig *config = [[GMSPlacePickerConfig alloc] initWithViewport:viewport];
_placePicker = [[GMSPlacePicker alloc] initWithConfig:config];
[_placePicker pickPlaceWithCallback:^(GMSPlace *place, NSError *error) {
if (error != nil) {
NSLog(#"Pick Place error %#", [error localizedDescription]);
return;
}
if (place != nil) {
NSLog(#"Place name %#", place.name);
NSLog(#"Place address %#", place.formattedAddress);
NSLog(#"Place attributions %#", place.attributions.string);
// NSString *latitudeValue = [NSString stringWithFormat:#"%f", locationManager.location.coordinate.latitude];
// NSString *longitudeValue = [NSString stringWithFormat:#"%f",locationManager.location.coordinate.longitude];
tfLocation.text=place.formattedAddress;
locationPoint=[NSString stringWithFormat:#"%f,%f", place.coordinate.latitude,place.coordinate.longitude];
} else {
NSLog(#"No place selected");
}
}];
}
// Add a UIButton in Interface Builder, and connect the action to this function.
- (IBAction)getCurrentPlace:(UIButton *)sender {
[_placesClient currentPlaceWithCallback:^(GMSPlaceLikelihoodList *placeLikelihoodList, NSError *error){
if (error != nil) {
NSLog(#"Pick Place error %#", [error localizedDescription]);
return;
}
self.nameLabel.text = #"No current place";
self.addressLabel.text = #"";
if (placeLikelihoodList != nil) {
GMSPlace *place = [[[placeLikelihoodList likelihoods] firstObject] place];
if (place != nil) {
self.nameLabel.text = place.name;
self.addressLabel.text = [[place.formattedAddress componentsSeparatedByString:#", "]
componentsJoinedByString:#"\n"];
}
}
}];
}
// Present the autocomplete view controller when the button is pressed.
- (IBAction)onLaunchClicked:(id)sender {
GMSAutocompleteViewController *acController = [[GMSAutocompleteViewController alloc] init];
acController.delegate = self;
[self presentViewController:acController animated:YES completion:nil];
}
// Handle the user's selection.
- (void)viewController:(GMSAutocompleteViewController *)viewController
didAutocompleteWithPlace:(GMSPlace *)place {
[self dismissViewControllerAnimated:YES completion:nil];
// Do something with the selected place.
NSLog(#"Place name %#", place.name);
NSLog(#"Place address %#", place.formattedAddress);
NSLog(#"Place attributions %#", place.attributions.string);
}
- (void)viewController:(GMSAutocompleteViewController *)viewController
didFailAutocompleteWithError:(NSError *)error {
[self dismissViewControllerAnimated:YES completion:nil];
// TODO: handle the error.
NSLog(#"Error: %#", [error description]);
}
// User canceled the operation.
- (void)wasCancelled:(GMSAutocompleteViewController *)viewController {
[self dismissViewControllerAnimated:YES completion:nil];
}
// Turn the network activity indicator on and off again.
- (void)didRequestAutocompletePredictions:(GMSAutocompleteViewController *)viewController {
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
}
- (void)didUpdateAutocompletePredictions:(GMSAutocompleteViewController *)viewController {
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
}
Can anyone tell, what am I doing wrong here? What is the best to use place picker without affecting background location updates or is there any other way to pick place/location just like google place picker in ios?
Please help me out or tell me the other solution.
thank you!

App crash while return from didFinishLaunchingWithOptions with error [UIButton rac_signalForControlEvents:]

App crash while return from didFinishLaunchingWithOptions method.
Getting error below.
2016-10-06 17:09:34.717 Mamabear[2655:51800] [Crashlytics] Version 3.8.2 (118)
2016-10-06 17:09:34.732 Mamabear[2655:51800] Flurry: Starting session on Agent Version [Flurry_iOS_187_7.8.0]
2016-10-06 17:09:34:738 Mamabear[2655:70b] Logging Initialized.
2016-10-06 17:09:34:738 Mamabear[2655:70b] Util Logging Initialized.
2016-10-06 17:09:34:738 Mamabear[2655:70b] Logging setup
2016-10-06 17:09:34.789 Mamabear[2655:51800] idfa class missing, won't collect idfa
2016-10-06 17:09:34.792 Mamabear[2655:51800] +[NSDate act_secondsSince1970]: unrecognized selector sent to class 0x10ad3ae08
2016-10-06 17:09:34.799 Mamabear[2655:51800] WARNING: GoogleAnalytics 3.08 void GAIUncaughtExceptionHandler(NSException *) (GAIUncaughtExceptionHandler.m:49): Uncaught exception: +[NSDate act_secondsSince1970]: unrecognized selector sent to class 0x10ad3ae08
2016-10-06 17:09:34.807 Mamabear[2655:51873] CoreData: warning: Unable to load class named 'GAIProperty' for entity 'GAIProperty'. Class not found, using default NSManagedObject instead.
2016-10-06 17:09:34.811 Mamabear[2655:51873] CoreData: warning: Unable to load class named 'GAIHit' for entity 'GAIHit'. Class not found, using default NSManagedObject instead.
2016-10-06 17:09:34.883 Mamabear[2655:51800] -[UIButton rac_signalForControlEvents:]: unrecognized selector sent to instance 0x7ffc70cc5770
libc++abi.dylib: terminate_handler unexpectedly threw an exception
I am also using multiple pod files in project.
I also have code regarding NSDate. please look at this.
-(void)saveCurrentTimeStamp{
NSDate *ExpDate=[NSDate date];
[[NSUserDefaults standardUserDefaults] setObject:ExpDate forKey:#"currentTimeStamp"];
[[NSUserDefaults standardUserDefaults]synchronize];
NSLog(#"saveCurrentTimeStamp....%#",[[NSUserDefaults standardUserDefaults]objectForKey:#"currentTimeStamp"]);
}
didfinishlauch code.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.timeNow=0;
[[NSUserDefaults standardUserDefaults]setInteger:0 forKey:#"countAdd"];
[[NSUserDefaults standardUserDefaults]synchronize];
//[self.timerForInterstitialAd invalidate];
//self.timerForInterstitialAd = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(updatetimerForInterstitialAd:) userInfo:nil repeats:YES];
[[NSUserDefaults standardUserDefaults]setBool:YES forKey:#"fstTimeLoad"];
[[NSUserDefaults standardUserDefaults]synchronize];
adZones = [NSArray array];
[Crashlytics startWithAPIKey:#"50a6f020b3dff7ef81c7b6e5fa4ca9f2a2694c2a"];
[Flurry setCrashReportingEnabled:NO];
[Flurry startSession:#"2R4ZDZQH4F8QYYN2V8PC"];
[Flurry setBackgroundSessionEnabled:NO];
[Ouralabs setAppVersion:[[[NSBundle mainBundle] infoDictionary] objectForKey:#"CFBundleVersion"]];
[Ouralabs initWithKey:#"7fbe83476d77bfcc71f14d104585bc0b"];
_fileLogger = [Util setupLogging];
[self setupLogging];
OULogInfo(#"AppDelegate", #"App started");
DDLogVerbose(#"Logging setup");
[self configureURLCache];
[self migrateUserDefaultsToGroupLevel];
//**************for debugging, write console to file
// [self redirectConsoleLogToDocumentFolder];
//**************
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
[MMSDK initialize];
// [self initAdAdaptedSDK];
NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:
// [UIColor whiteColor], NSForegroundColorAttributeName,
[UIFont fontWithName:#"Avenir" size:16.0f], NSFontAttributeName, nil];
[[UIBarButtonItem appearance] setTitleTextAttributes: attributes
forState: UIControlStateNormal];
//--------------------------------------------------------------------------------------------
// Set userdefaults with the default values
//--------------------------------------------------------------------------------------------
// CFBundleVersion returns build number
// NSString *bundleVersion = [[[NSBundle mainBundle] infoDictionary] objectForKey:#"CFBundleVersion"];
// NSString *version = [[[NSBundle mainBundle] infoDictionary] objectForKey:#"CFBundleShortVersionString"];
// CFBundleShortVersionString returns version in General identify settings
NSString *bundleVersion = [[[NSBundle mainBundle] infoDictionary] objectForKey:#"CFBundleShortVersionString"];
[MAMABEAR_GROUP_DEFAULTS setObject:[NSString stringWithFormat:#"%#", bundleVersion] forKey:#"version"];
//--------------------------------------------------------------------------------------------
// Environment Settings
//--------------------------------------------------------------------------------------------
#if USE_PRODUCTION_ENVIRONMENT
// ************************************** PRODUCTION ************************************** \\
//--------------------------------------------------------------------------------------------
[MAMABEAR_GROUP_DEFAULTS setObject:#"https://api.mamabearapp.com" forKey:MBMainServerURL];
[MAMABEAR_GROUP_DEFAULTS setObject:#"https://api.mamabearapp.com" forKey:MBCoordinateServerURL];
[MAMABEAR_GROUP_DEFAULTS setObject:#"https://api.mamabearapp.com/time" forKey:MBReachabilityServerURL];
[MAMABEAR_GROUP_DEFAULTS setObject:#"https://analytics.mamabearapp.com/v1/" forKey:MBAnalyticsServerURL];
//--------------------------------------------------------------------------------------------
#else
// ****************************************** UAT ***************************************** \\
//--------------------------------------------------------------------------------------------
[MAMABEAR_GROUP_DEFAULTS setObject:#"http://api-uat.mamabearapp.com" forKey:MBMainServerURL];
[MAMABEAR_GROUP_DEFAULTS setObject:#"http://api-uat.mamabearapp.com" forKey:MBCoordinateServerURL];
[MAMABEAR_GROUP_DEFAULTS setObject:#"http://api-uat.mamabearapp.com/time" forKey:MBReachabilityServerURL];
[MAMABEAR_GROUP_DEFAULTS setObject:#"https://analytics-uat.mamabearapp.com/v1/" forKey:MBAnalyticsServerURL];
//--------------------------------------------------------------------------------------------
#endif
// ************************************ Other Environments *********************************** \\
//[MAMABEAR_GROUP_DEFAULTS setObject:#"172.16.168.99:8080/mamabear" forKey:MBMainServerURL]; //Nate LOCAL Environment
//[MAMABEAR_GROUP_DEFAULTS setObject:#"10.10.0.134:8080/mamabear" forKey:MBMainServerURL]; //Mac mini LOCAL Environment
//[MAMABEAR_GROUP_DEFAULTS setObject:#"ec2-23-22-115-247.compute-1.amazonaws.com/mamabear" forKey:MBMainServerURL]; // Uncomment for QA server
//--------------------------------------------------------------------------------------------
// AFNetworking Reachability
//--------------------------------------------------------------------------------------------
NSURL *reachabilityServerURL = [NSURL URLWithString:[MAMABEAR_GROUP_DEFAULTS objectForKey:MBReachabilityServerURL]];
AFHTTPRequestOperationManager *manager = [[AFHTTPRequestOperationManager alloc] initWithBaseURL:reachabilityServerURL];
[manager.reachabilityManager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
//NSLog(#"Reachability (%#): %#",[MAMABEAR_GROUP_DEFAULTS objectForKey:MBReachabilityServerURL],
// AFStringFromNetworkReachabilityStatus(status));
}];
[manager.reachabilityManager startMonitoring];
[[MBAnalyticsHTTPClient sharedClient] getConfigWithCompletion:^(BOOL active, NSError *error) {
if (error) {
[MAMABEAR_GROUP_DEFAULTS setBool:FALSE forKey:#"MBAnalyticsActiveFlag"];
[MAMABEAR_GROUP_DEFAULTS synchronize];
return ;
}
[MAMABEAR_GROUP_DEFAULTS setBool:active forKey:#"MBAnalyticsActiveFlag"];
[MAMABEAR_GROUP_DEFAULTS synchronize];
if (active) {
NSString *uniqueAnalyticsId = [MAMABEAR_GROUP_DEFAULTS objectForKey:#"MBAnalyticsUniqueId"];
if (!uniqueAnalyticsId || [uniqueAnalyticsId isEqualToString:#""]) {
[[MBAnalyticsHTTPClient sharedClient] getUniqueDeviceIdWithCompletion:^(NSString *uniqueId, NSError *error) {
if (error) {
[MAMABEAR_GROUP_DEFAULTS setObject:#"" forKey:#"MBAnalyticsUniqueId"];
[MAMABEAR_GROUP_DEFAULTS synchronize];
}
if (uniqueId && ![uniqueId isEqualToString:#""]){
[MAMABEAR_GROUP_DEFAULTS setObject:uniqueId forKey:#"MBAnalyticsUniqueId"];
[MAMABEAR_GROUP_DEFAULTS synchronize];
}
else {
[MAMABEAR_GROUP_DEFAULTS setObject:#"" forKey:#"MBAnalyticsUniqueId"];
[MAMABEAR_GROUP_DEFAULTS synchronize];
}
}];
}
}
[[MBAnalyticsHTTPClient sharedClient] updateDevice:device completion:^(BOOL status, NSError *error) {
if (error) {
OULogError(NSStringFromClass([self class]), #"Failed to update device for analytics.", #{#"error": error.userInfo.debugDescription});
}
if (status) {
OULogInfo(NSStringFromClass([self class]), #"Updated device for analytics.");
}
else {
OULogError(NSStringFromClass([self class]), #"Failed to update device for analytics. Status not 200.");
}
}];
}
}];
//--------------------------------------------------------------------------------------------
// Initialize Batch ID (idk if we need this)
//--------------------------------------------------------------------------------------------
if ([MAMABEAR_GROUP_DEFAULTS objectForKey: #"batchId"] == nil)
{
[MAMABEAR_GROUP_DEFAULTS setObject:#"1" forKey: #"batchId"];
}
[MAMABEAR_GROUP_DEFAULTS synchronize];
//--------------------------------------------------------------------------------------------
// When lauching, check for the phone number in user defaults and set keychain. (Steve Wilson)
//--------------------------------------------------------------------------------------------
if (!phoneNumberItem)
{
phoneNumberItem = [[KeychainItemWrapper alloc] initWithIdentifier:#"MamaBearApp_Creds" accessGroup:nil];
}
if ([MAMABEAR_GROUP_DEFAULTS objectForKey:#"phoneNumber"] && ![phoneNumberItem objectForKey:(__bridge id)kSecAttrAccount])
{
//NSLog(#"****Setting keychain values from UserDefaults");
[self setBackgroundKeychainValues:[MAMABEAR_GROUP_DEFAULTS objectForKey:#"phoneNumber"] :[MAMABEAR_GROUP_DEFAULTS objectForKey:#"coordinateServerUrl"] :[MAMABEAR_GROUP_DEFAULTS objectForKey:#"userId"] :[MAMABEAR_GROUP_DEFAULTS objectForKey:#"name"]];
}
//--------------------------------------------------------------------------------------------
// Initialize Instagram SDK
//--------------------------------------------------------------------------------------------
self.instagram = [[Instagram alloc] initWithClientId:APP_ID delegate:nil];
//--------------------------------------------------------------------------------------------
// Initialize Cubs & Guardians
//--------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------
// Set up the CLController delegate so we can send to the server.
//--------------------------------------------------------------------------------------------
locationUpdateController = [[LocationUpdateController alloc] init];
//NSUserDefaults *InterstitialObject;
[[NSUserDefaults standardUserDefaults] setInteger:0 forKey:#"InterstitialCount"];
[[NSUserDefaults standardUserDefaults] setInteger:0 forKey:#"InterstitialTime"];
//--------------------------------------------------------------------------------------------
// Set up the alert badge
//--------------------------------------------------------------------------------------------
alertCountOBJ = [AlertCount sharedAlertCounts];
application.applicationIconBadgeNumber = 0;
//--------------------------------------------------------------------------------------------
// Set up the Master View Controller
//--------------------------------------------------------------------------------------------
MBWelcomeViewController *masterVC = [[MBWelcomeViewController alloc] init];
self.navigationController = [[UINavigationController alloc] initWithRootViewController:masterVC];
// navigationbar
// self.navigationController.navigationBar.barStyle = UIBarStyleBlackOpaque;
self.window.rootViewController = self.navigationController;
[self.window makeKeyAndVisible];
//--------------------------------------------------------------------------------------------
// Register for Remote Notifications
//--------------------------------------------------------------------------------------------
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeBadge |
UIUserNotificationTypeSound |
UIUserNotificationTypeAlert) categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:settings];
//--------------------------------------------------------------------------------------------
// Handle Launching from a notification
//--------------------------------------------------------------------------------------------
UILocalNotification *localNotif = [launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey];
if (localNotif)
{
//NSLog(#"Recieved Notification %#",localNotif);
}
//--------------------------------------------------------------------------------------------
// Initialize Background Fetch Interval if iOS7 or greater
//--------------------------------------------------------------------------------------------
if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1)
{
//set minimum number of seconds between background. This will call performFetchWithCompletionHandler
[[UIApplication sharedApplication] setMinimumBackgroundFetchInterval:300];
}
//--------------------------------------------------------------------------------------------
// App was launched from a Location Update (Steve Wilson)
//--------------------------------------------------------------------------------------------
if ([launchOptions objectForKey:UIApplicationLaunchOptionsLocationKey])
{
DDLogVerbose(#"************MamaBear Re-Launched from Background - LOCATION UPDATE*********");
CLController = [CoreLocationController sharedInstance];
[CLController startMonitoringSignificantLocationChanges];
[MAMABEAR_GROUP_DEFAULTS synchronize];
__block UIBackgroundTaskIdentifier bgTaskEnter;
bgTaskEnter = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
[CLController stopUpdatingLocation];
[CLController startMonitoringSignificantLocationChanges];
DDLogVerbose(#"****App Relaunched --> GPS Background Task Out of Time*******");
[[UIApplication sharedApplication] endBackgroundTask:bgTaskEnter];
bgTaskEnter = UIBackgroundTaskInvalid;
}];
// Start the long-running task on an expiration.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
DDLogVerbose(#"****App Relaunched --> Starting background GPS on Timeout*****");
[CLController startUpdatingLocation];
[[UIApplication sharedApplication] endBackgroundTask:bgTaskEnter];
bgTaskEnter = UIBackgroundTaskInvalid;
});
}
//--------------------------------------------------------------------------------------------
// Initialize Appearance
//--------------------------------------------------------------------------------------------
[[[self navigationController] navigationBar] setBackgroundImage: [UIImage imageNamed:#"nav_bar_orange.png"]
forBarMetrics: UIBarMetricsDefault];
[[UINavigationBar appearance] setBackgroundImage: [UIImage imageNamed: #"nav_bar_orange.png"]
forBarMetrics: UIBarMetricsDefault];
// blackcolor
[[UINavigationBar appearance] setTintColor: [UIColor whiteColor]];
NSShadow *shadow = [[NSShadow alloc] init];
shadow.shadowOffset = CGSizeZero;
NSDictionary *titleTextAttributes =
#{
NSForegroundColorAttributeName: [UIColor whiteColor],
NSFontAttributeName: [UIFont fontWithName:#"Avenir-Light" size:28],
NSShadowAttributeName: shadow
};
[[UINavigationBar appearance] setTitleTextAttributes:titleTextAttributes];
if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_6_1)
{
UIImage *backButtonImage = nil;
backButtonImage = [[UIImage imageNamed:#"iOS_blank_back_button"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 15, 0, 10) resizingMode:UIImageResizingModeStretch];
[[UIBarButtonItem appearance] setBackButtonBackgroundImage:backButtonImage forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
}
//--------------------------------------------------------------------------------------------
// MamaBear BI Recording
//--------------------------------------------------------------------------------------------
if ([MAMABEAR_GROUP_DEFAULTS objectForKey:#"userId"] != nil && [MAMABEAR_GROUP_DEFAULTS objectForKey:#"userId"] != 0)
{
NSDictionary *parameters = #{#"userId": [MAMABEAR_GROUP_DEFAULTS objectForKey:#"userId"], #"slat": [NSString stringWithFormat: #"%.07f",CLController.locationManager.location.coordinate.latitude], #"slng": [NSString stringWithFormat: #"%.07f",CLController.locationManager.location.coordinate.longitude]};
[[MBMainHTTPClient sharedClient] sendForegroundStatus:parameters completion:nil];
if (![[MAMABEAR_GROUP_DEFAULTS objectForKey:#"role"] isEqualToString: #"mama"])
{
application.applicationIconBadgeNumber = 0;
}
}
else
{
[MAMABEAR_GROUP_DEFAULTS setObject: [NSDate date] forKey: #"foregroundTime"];
}
//--------------------------------------------------------------------------------------------
// Initialize Google Analytics
//--------------------------------------------------------------------------------------------
[GAI sharedInstance].dispatchInterval = 20;
[GAI sharedInstance].trackUncaughtExceptions = YES;
self.tracker = [[GAI sharedInstance] trackerWithTrackingId:kTrackingId];
//--------------------------------------------------------------------------------------------
// HasOffers SDK Integration
//--------------------------------------------------------------------------------------------
NSString * const MAT_CONVERSION_KEY = #"83020f2524e98767f2319ed4ca09abcd";
NSString * const MAT_ADVERTISER_ID = #"13098";
[MobileAppTracker initializeWithMATAdvertiserId:MAT_ADVERTISER_ID MATConversionKey:MAT_CONVERSION_KEY];
[MobileAppTracker setAppleAdvertisingIdentifier:[[ASIdentifierManager sharedManager] advertisingIdentifier]
advertisingTrackingEnabled:[[ASIdentifierManager sharedManager] isAdvertisingTrackingEnabled]];
//--------------------------------------------------------------------------------------------
// Google Adwords Tracking
//--------------------------------------------------------------------------------------------
[ACTConversionReporter reportWithConversionID:#"997118172" label:#"yKOXCIzOgAsQ3KG72wM" value:#"0.000000" isRepeatable:NO];
return YES;
}

Objective C IOS - SingalR 2 don't connect in background fetch

I have created an app with SignalR Ver 2. SignalR works when the app is in the foreground, but when the app is backgrounded SignalR is not connecting! There is one thing I don't understand; when I test the app in the simulator using objective c it works and connects but it don't work when I send the app to my phone!
-(void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
if ([[NSUserDefaults standardUserDefaults]stringForKey:#"UserName"]) {
//[self performBackgroundTask];
}
completionHandler (UIBackgroundFetchResultNewData);
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
if ([UIApplication instancesRespondToSelector:#selector(registerUserNotificationSettings:)]){
[application registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|UIUserNotificationTypeSound categories:nil]];
}
// Override point for customization after application launch.
return YES;
}
- (void)performBackgroundTask
{
NSString *buf = [[NSUserDefaults standardUserDefaults]stringForKey:#"UserName"];
connection = [SRHubConnection connectionWithURL:#"http://yoursite.com/"];
myHub = [connection createHubProxy:#"MobileNotification"];
NSLog(#"%#",myHub);
connection.started = ^{
[myHub invoke:#"init" withArgs:[NSArray arrayWithObjects: buf, nil]];
};
connection.reconnected =^{
[myHub invoke:#"init" withArgs:[NSArray arrayWithObjects: buf, nil]];
};
[myHub on:#"agentMessage" perform:self selector:#selector(notificationReceived::)];
[connection setDelegate:self];
[connection start];
[UIApplication sharedApplication].applicationIconBadgeNumber = 0;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
});
}
- (void)notificationReceived:(NSString*)RecipientId:(id)message
{
NSDictionary *json = message;
int RId = [[json objectForKey:#"RecipientId"] integerValue];
[json objectForKey:#"Username"];
NSString *body = [json objectForKey:#"Body"];
NSString *time = [json objectForKey:#"CreationTime"];
UILocalNotification* localNotification = [[UILocalNotification alloc] init];
localNotification.fireDate = [NSDate date];
localNotification.alertBody = [NSString stringWithFormat:#"%# - %#",body,time];
localNotification.timeZone = [NSTimeZone defaultTimeZone];
static int i=1;
[UIApplication sharedApplication].applicationIconBadgeNumber = i++;
[[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
[myHub invoke:#"UpdateStatus" withArgs:[NSArray arrayWithObjects:[NSNumber numberWithInteger:RId],#"Delivered", nil]];
}
Please tell me what solution is better for background service and SignalR?
Best Regard
Mani

How to handle remote notifications when the app is not running

If my app is running on foreground or background this working fine. I am receiving the notifications and save it on the local database. But if the app killed from the background it receives the remote notifications but the following method is not called. And the issue is if I tap any one of the notification,only that notification will saved on the local database.
- (void)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))handler
{
[PFPush handlePush:userInfo];
NSLog(#"Received notification: %#", userInfo);
NSString *alertString = [[userInfo objectForKey:#"aps"]valueForKey:#"alert"];
NSLog(#"%#",alertString);
NSString *msgType = [userInfo objectForKey:#"messageType"];
NSString *senderId = [userInfo objectForKey:#"senderId"];
NSString *receverId = [userInfo objectForKey:#"receverId"];
NSString *msg = [userInfo objectForKey:#"message"];
NSString *timeStr = [userInfo objectForKey:#"Time"];
NSLog(#"msg type%# senderId %# receverId %# message %#",msgType,senderId,receverId,msg);
if ([AppDelegate isNetworkReachable]){
if ([msgType isEqualToString:#"CHAT"]) {
Chatmessage *Cmsg=[[Chatmessage alloc]init];
Cmsg.chat_date =timeStr;
Cmsg.chat_image =#"";
Cmsg.chat_message = msg;
Cmsg.chat_Receiver_Id = receverId;
Cmsg.chat_Sender_Id = senderId;
NSLog(#"recid%#",Cmsg.chat_Receiver_Id);
NSMutableArray *arryMsg = [[NSMutableArray alloc]init];
arryMsg = [[DBModelNew database]getChatMessageBasedOnTime:receverId SenId:senderId time_stamp:timeStr message:msg];
if (arryMsg.count == 0) {
[[DBModelNew database]insertmsg:Cmsg];
}
[[NSNotificationCenter defaultCenter]postNotificationName:#"receivedmessage" object:nil];
chatHistory *chatObj = [[chatHistory alloc]init];
chatObj.chat_meta_id = [NSString stringWithFormat:#"%#",senderId];
chatObj.last_send_message = msg;
NSDateFormatter* dateFormatter = [[NSDateFormatter alloc] init];
dateFormatter.dateFormat = #"yyyy-MM-dd HH:mm:ss";
NSString *str=[dateFormatter stringFromDate:[NSDate date]];
chatObj.last_time_stamp = [self dateformat:str];
PFQuery *query = [PFUser query];
[query whereKey:#"objectId" equalTo:senderId];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
for (NSDictionary *dict in objects) {
[[dict objectForKey:#"ProfilePic"] getDataInBackgroundWithBlock:^(NSData *data, NSError *error) {
if (!error) {
if (data) {
UIImage *image = [UIImage imageWithData:data];
if (image) {
chatObj.fndimage = image;
chatObj.name = [dict objectForKey:#"name"];
[[DBModelNew database]insertChat:chatObj];
[[NSNotificationCenter defaultCenter]postNotificationName:#"receivedNewMessage" object:nil];
}
}
}
}];
}
}
}];
}
}
}
From the Apple docs, if the user hard closes the app it does not call the method.
In addition, if you enabled the remote notifications background mode,
the system launches your app (or wakes it from the suspended state)
and puts it in the background state when a remote notification
arrives. However, the system does not automatically launch your app if
the user has force-quit it. In that situation, the user must relaunch
your app or restart the device before the system attempts to launch
your app automatically again.
If you want to launch specific payload dictionary from viewDidLoad then you simply call the following :
UILocalNotification *localNotif =
[launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey];
And you get the userInfo this way:
NSString *msgType = [localNotif objectForKey:#"messageType"];
And now you can act accordingly. This is just for the circumstances you stated in your title. When the app is not 'running' (terminated)

IOS Queue Asynchronous downloads

I am facing an issue making a queue of asynchronous downloads of 3 files.
I would like when I finish to download and saved the first files to start to download the second one then third one ...
For the moment I am using 3 IBAction to download into Documents folder and it work perfectly, but to make it automatically for all files didnĀ“t work.
What is the best way to implement the download queue of this files ?
I know i have to had statements on didReceiveData but I need help to make it working.
This is the code I am using :
// Download song 1
- (IBAction)download {
[self performSelector:#selector(downloadmusic) withObject:nil afterDelay:0.0];
}
- (void)downloadmusic
{
self.log = [NSMutableString string];
[self doLog:#"1/13"];
// Retrieve the URL string
int which = [(UISegmentedControl *)self.navigationItem.titleView selectedSegmentIndex];
NSArray *urlArray = [NSArray arrayWithObjects: SONG1_URL, nil];
NSString *urlString = [urlArray objectAtIndex:which];
// Prepare for download
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
// Set up the Download Helper and start download
[DownloadHelper sharedInstance].delegate = self;
[DownloadHelper download:urlString];
}
// Download song 2
- (void)downloadmusic2
{
self.log = [NSMutableString string];
[self doLog:#"2/13"];
// Retrieve the URL string
int which = [(UISegmentedControl *)self.navigationItem.titleView selectedSegmentIndex];
NSArray *urlArray = [NSArray arrayWithObjects: SONG2_URL, nil];
NSString *urlString = [urlArray objectAtIndex:which];
// Prepare for download
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
// Set up the Download Helper and start download
[DownloadHelper sharedInstance].delegate = self;
[DownloadHelper download:urlString];
}
// Download song 3
- (void)downloadmusic3
{
self.log = [NSMutableString string];
[self doLog:#"3/13"];
// Retrieve the URL string
int which = [(UISegmentedControl *)self.navigationItem.titleView selectedSegmentIndex];
NSArray *urlArray = [NSArray arrayWithObjects: SONG3_URL, nil];
NSString *urlString = [urlArray objectAtIndex:which];
// Prepare for download
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
// Set up the Download Helper and start download
[DownloadHelper sharedInstance].delegate = self;
[DownloadHelper download:urlString];
}
- (void) doLog: (NSString *) formatstring, ...
{
va_list arglist;
if (!formatstring) return;
va_start(arglist, formatstring);
NSString *outstring = [[[NSString alloc] initWithFormat:formatstring arguments:arglist] autorelease];
va_end(arglist);
[self.log appendString:outstring];
[self.log appendString:#"\n"];
[textView setText:self.log];
}
- (void) restoreGUI
{
self.navigationItem.rightBarButtonItem = BARBUTTON(#"Get Data", #selector(action:));
if ([[NSFileManager defaultManager] fileExistsAtPath:DEST_PATH])
self.navigationItem.leftBarButtonItem = BARBUTTON(#"Play", #selector(startPlayback:));
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
[(UISegmentedControl *)self.navigationItem.titleView setEnabled:YES];
[progress setHidden:YES];
}
- (void) dataDownloadAtPercent: (NSNumber *) aPercent
{
[progress setHidden:NO];
[progress setProgress:[aPercent floatValue]];
}
- (void) dataDownloadFailed: (NSString *) reason
{
[self restoreGUI];
if (reason) [self doLog:#"Download failed: %#", reason];
}
- (void) didReceiveFilename: (NSString *) aName
{
self.savePath = [DEST_PATH stringByAppendingString:aName];
}
- (void) didReceiveData: (NSData *) theData
{
if (![theData writeToFile:self.savePath atomically:YES])
[self doLog:#"Error writing data to file"];
[theData release];
[self restoreGUI];
[self doLog:#"Download succeeded"];
//[self performSelector:#selector(downloadmusic2) withObject:nil afterDelay:1.0];
//[self performSelector:#selector(downloadmusic3) withObject:nil afterDelay:1.0];
}
From within your controller, create three blocks and copy them to an array, which will serve as your queue. This array will need to be stored as an instance variable so that it can be accessed by later invocations of methods in your controller class. Each of the three blocks should create and execute an NSURLConnection which asynchronously downloads the appropriate file. The delegate of each NSURLConnection can be your controller, and it should implement the -connectionDidFinishLoading: delegate method. From this method, call a method which pops the first block off the queue and executes it.
Then just call the method for the first time to start the process. Obviously there is some edge-case and error handling that you need to provide, but this is the basic idea.

Resources