I handle push notification when the screen is on by automatically push to a detailViewController. It works fine when there is one or two push notification as I can push each detailViewController on top of each other and pop it back. However, app crash when I have to pop back more than two detailViewControllers. It happens only in iOS 7+.
Set notification Id
- (void)application:(UIApplication *)app didReceiveRemoteNotification:(NSDictionary *)userInfo
{
if(app.applicationIconBadgeNumber!=0)
{
app.applicationIconBadgeNumber = app.applicationIconBadgeNumber - 1;
}
NSString *aps =[NSString stringWithFormat:#"%#",[userInfo objectForKey:#"id"]];
if (app.applicationState == UIApplicationStateActive)
{
NSDictionary *dict = [NSDictionary dictionaryWithObjects:#[[[userInfo objectForKey:#"aps"] objectForKey:#"alert"]] forKeys:#[#"notifyText"]];
[arrNotificationData addObject:dict];
[self showNotificationInActiveMode:[[userInfo objectForKey:#"aps"] objectForKey:#"alert"]];
}
if ([aps isEqualToString:#"1"])
{
[UserDefault setpushnotificationid:[aps intValue]];
}
if ([aps isEqualToString:#"2"])
{
[UserDefault setpushnotificationid:[aps intValue]];
}
if ([aps isEqualToString:#"3"])
{
[UserDefault setpushnotificationid:[aps intValue]];
}
if ([aps isEqualToString:#"4"])
{
[UserDefault setpushnotificationid:[aps intValue]];
}if ([aps isEqualToString:#"5"])
{
[UserDefault setpushnotificationid:[aps intValue]];
}
}
Use singleton class as base class and check for ID and the push and pop the view.
#interface CustomViewController ()
#end
#implementation CustomViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter]addObserver:self
selector:#selector(appBecomeActive)
name:UIApplicationDidBecomeActiveNotification
object:nil];
}
-(void)appBecomeActive
{
int val=[UserDefault getpushnotificationid];
if(val!=0){
[self checkforpushnotification];
}
}
-(void)checkforpushnotification
{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
int val=[UserDefault getpushnotificationid];
[UserDefault setpushnotificationid:0];
//.: if current view is profile or setting just dismiss it.because they are present
switch (val)
{
case 1:
{
if( [self checkIfControllerExist:[DealsViewController class]])
{
return;
}else{
detailViewController *VC = (detailViewController *)[storyboard instantiateViewControllerWithIdentifier:#"VCView"];
[self.navigationController pushViewController:VC animated:YES];
}
}
break;
}
}
Now use bace class in your class
#interface detailViewController : CustomViewController
Related
I have an iOS application in which I am using the push notification to notify the user when the correct answer is posted. If the application is open and if I click on the notification it goes to the specified controller. But if the application is closed and if I receive the notification it does not goes to the specified controller.
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
NSLog(#"User Info %#",userInfo);
NSString* alertValue = [[userInfo valueForKey:#"aps"] valueForKey:#"badge"];
NSLog(#"my message-- %#",alertValue);
int badgeValue= [alertValue intValue];
// NSNumber *identifierString = [[[userInfo valueForKey:#"aps"]valueForKey:#"details"]valueForKey:#"identifire"];
// NSLog(#"identifierString %#",identifierString);
NSString *alertMessage = [[userInfo valueForKey:#"aps"] valueForKey:#"alert"];
NSLog(#"ALertMessage %#",alertMessage);
if ([alertMessage isEqualToString:#"New answer added."]) {
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:badgeValue];
// [[NSUserDefaults standardUserDefaults] setObject:[[[[userInfo valueForKey:#"aps"] valueForKey:#"details"] objectAtIndex:0]valueForKey:#"question"]forKey:#"notificationQuestion"];
// [[NSUserDefaults standardUserDefaults] setObject:[[[[userInfo valueForKey:#"aps"] valueForKey:#"details"] objectAtIndex:0]valueForKey:#"user_image"]forKey:#"notificationImage"];
// NSLog(#"Image %#",[[NSUserDefaults standardUserDefaults]valueForKey:#"notificationQuestion"]);
NSLog(#"User Information %#",userInfo);
NSLog(#"User Details %#",[[userInfo valueForKey:#"aps"] valueForKey:#"details"]);
// NSLog(#"User Details 1%#",[[[userInfo valueForKey:#"aps"] valueForKey:#"details"] objectAtIndex:0]);
// NSLog(#"User Details 1%#",[[[[userInfo valueForKey:#"aps"] valueForKey:#"details"] objectAtIndex:0]valueForKey:#"question"]);
pushDictonary = [[userInfo valueForKey:#"aps"] valueForKey:#"details"];
}
//NSArray *pushDetails = [[userInfo valueForKey:#"aps"] valueForKey:#"details"];
// NSLog(#"Push Details %#",pushDetails);
if (application.applicationState == UIApplicationStateActive ) {
// UILocalNotification *localNotification = [[UILocalNotification alloc] init];
// localNotification.userInfo = userInfo;
// localNotification.soundName = UILocalNotificationDefaultSoundName;
// localNotification.alertBody = [[userInfo valueForKey:#"aps"] valueForKey:#"alert"];
// localNotification.fireDate = [NSDate date];
if ([alertMessage isEqualToString:#"New answer added."])
{
[self createNotificationViewwithUserDictionary:userInfo];
}
}
else if (application.applicationState == UIApplicationStateBackground)
{
NSLog(#"YES");
}
else if (application.applicationState == UIApplicationStateInactive)
{
NSLog(#"YES");
if ([alertMessage isEqualToString:#"New answer added."])
[self pushdetailsViewController];
}
For going to the controller :
-(void)pushdetailsViewController
{
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"Main" bundle: nil];
QPYourQuestionController *controller = (QPYourQuestionController*)[mainStoryboard instantiateViewControllerWithIdentifier: #"yourQuestion"];
[[QPCommonClass initializeUserDefaults]setObject:[pushDictonary valueForKey:#"question_id"] forKey:#"currentquestionID"];
NSLog(#"Dictionary %#",pushDictonary);
UINavigationController *navigationController = (UINavigationController *)self.window.rootViewController;
[navigationController pushViewController:controller animated:YES];
}
For the situation when application is closed the remote notification delegate
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
is not called
In this case the call goes to the following method:
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
Hence you can do this to take the user to the VC you want
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// ...
if (launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey]) {
// Do whatever you want
}
}
add this code to your app delegate file
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
//you will get notification data in userInfo dict
UIStoryboard * mainStoryboard = [UIStoryboard storyboardWithName:#"Main" bundle: nil];
notificationViewController * notificationVC = [mainStoryboard instantiateViewControllerWithIdentifier: #"notificationViewController"];//set your controller here
[(UINavigationController *)self.window.rootViewController pushViewController:notificationVC animated:YES];
completionHandler(UIBackgroundFetchResultNewData);
}
I am trying to connect notifications when the app is closed. I need to get a message from APNS and open the desired article by id. The problem is that the message is not read by APNS inside the function didFinishLaunchingWithOptions. I do not know where the mistake. I'm trying to parse (NSDictionary *) launchOptions and pull out the id of the article. Inside the function - didReceiveRemoteNotification everything works fine.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[self settingMenuNotification];
[self restKitConfiguration];
[self registerSettingsAndCategories];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSLog(#"%#",[paths objectAtIndex:0]);
if(launchOptions != NULL) {
NSDictionary *userInfo = [launchOptions valueForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
NSDictionary *apsInfo = [userInfo objectForKey:#"aps"];
[self openNewsDetailNotification:apsInfo];
}
return YES;
}
-(void) openNewsDetailNotification:(NSDictionary*)apsInfo {
if( [apsInfo objectForKey:#"id"] != NULL) { //id - id_article
NSString *id_article = [apsInfo objectForKey:#"id"];
NSNumber *objectId = [NSNumber numberWithInteger: [id_article integerValue]];
NSLog(#"Получил id %#", id_article);
// Загружаем статью
UIWindow *window=[UIApplication sharedApplication].keyWindow;
UIViewController *root = [window rootViewController];
UIStoryboard *storyboard = root.storyboard;
NewsDetailViewController *newsVC = (NewsDetailViewController*)[storyboard instantiateViewControllerWithIdentifier:#"NewsDetailViewController"];
newsVC.objectId = objectId;
UINavigationController *navController = (UINavigationController *)self.window.rootViewController;
[navController.visibleViewController.navigationController pushViewController:newsVC animated:YES];
}
}
Same happened with me.I had added delay in that.Use this code instead of directly calling the function.
[self performSelector:#selector(openNewsDetailNotification:) withObject:apsInfo afterDelay:6.0f];
I am creating a Chat kind of iPhone application using Apple push notification services. APN's is working fine and i am getting notification when user is receiving new message. So, i have set one Toast pop up in didReceiveRemoteNotification of my App Delegate class. The problem is, i am getting Toast pop up in every View Controller screen because i have added Toast on my main window itself. but can you please help me that how can i hide this Toast pop up from one of my Chat List View Controller screen. How can i check which View Controller is loaded currently on my window view, when application is in foreground?
here is my code :
- (void)application:(UIApplication*)application didReceiveRemoteNotification:(NSDictionary*)userInfo
{
if ( application.applicationState == UIApplicationStateActive ){
NSString *personName = [[userInfo valueForKey:#"aps"] valueForKey:#"user_name"];
NSString *meassge = [NSString stringWithFormat:#"New message from %#.", personName];
[[self window] makeToast:meassge duration:1.0 position:#"center"];
[[NSNotificationCenter defaultCenter] postNotificationName:#"reloadTheTable" object:nil];
}
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:0];
[[UIApplication sharedApplication] cancelAllLocalNotifications];
}
Thanks!
Declare below methods in AppDelegate.m
- (UIViewController*)topViewController {
return [self topViewControllerWithRootViewController:[UIApplication sharedApplication].keyWindow.rootViewController];
}
- (UIViewController*)topViewControllerWithRootViewController:(UIViewController*)rootViewController {
if ([rootViewController isKindOfClass:[UITabBarController class]]) {
UITabBarController* tabBarController = (UITabBarController*)rootViewController;
return [self topViewControllerWithRootViewController:tabBarController.selectedViewController];
} else if ([rootViewController isKindOfClass:[UINavigationController class]]) {
UINavigationController* navigationController = (UINavigationController*)rootViewController;
return [self topViewControllerWithRootViewController:navigationController.visibleViewController];
} else if (rootViewController.presentedViewController) {
UIViewController* presentedViewController = rootViewController.presentedViewController;
return [self topViewControllerWithRootViewController:presentedViewController];
} else {
return rootViewController;
}
}
- (void)application:(UIApplication*)application didReceiveRemoteNotification:(NSDictionary*)userInfo
{
if ( application.applicationState == UIApplicationStateActive ){
NSString *personName = [[userInfo valueForKey:#"aps"] valueForKey:#"user_name"];
NSString *meassge = [NSString stringWithFormat:#"New message from %#.", personName];
if(![[self topViewController] isKindOfClass:[ChatListViewController class]])//ChatListViewController is your viewcontroller
[[self window] makeToast:meassge duration:1.0 position:#"center"];
[[NSNotificationCenter defaultCenter] postNotificationName:#"reloadTheTable" object:nil];
}
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:0];
[[UIApplication sharedApplication] cancelAllLocalNotifications];
}
When I login to my app, my app does push the ViewController XYZMainViewController, XYZMainViewController viewWillAppear:animated call method that makes a request to my API to retrieve the authenticated user data, at this time I update the text of a label to show the user name. When I logout the app, it returns me to the login ViewController, when I do login again with another user, XYZMainViewController label text contains the name of the previous user, without updating the label text.
XYZMainViewController.m
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self.navigationController setNavigationBarHidden:YES animated:NO];
[self homeProfile];
}
- (void)homeProfile
{
[NXOAuth2Request performMethod:#"GET"
onResource:[NSURL URLWithString:#"http://{url}/users/userinfo"]
usingParameters:nil
withAccount:[XYZCommonFunctions user]
sendProgressHandler:nil
responseHandler:^(NSURLResponse *response, NSData *responseData, NSError *error){
NSDictionary *parsedData = [[NSJSONSerialization JSONObjectWithData:responseData options:0 error:&error] objectForKey:#"data"];
_user = [parsedData objectForKey:#"user"];
[self.label setText:[NSString stringWithFormat:#"Welcome %#!", [_user objectForKey:#"username"]]];
}];
}
- (IBAction)logout:(id)sender {
XYZAppDelegate* appDelegate = (XYZAppDelegate*)[[UIApplication sharedApplication] delegate];
[appDelegate logout];
}
XYZAppDelegate.m
- (void)login
{
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
NSString *identifier = [prefs stringForKey:#"accountidentifier"];
UINavigationController *navigationController = (UINavigationController *)self.window.rootViewController;
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"Main" bundle: nil];
NSString *viewIdentifier = #"WelcomeView";
if(identifier != nil){
NXOAuth2Account *account = [[NXOAuth2AccountStore sharedStore] accountWithIdentifier:identifier];
if(account != nil) {
viewIdentifier = #"MainView";
}
UIViewController *controller = [mainStoryboard instantiateViewControllerWithIdentifier: viewIdentifier];
[navigationController pushViewController:controller animated:NO];
return;
}
}
- (void)logout
{
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
[prefs removeObjectForKey:#"accountidentifier"];
[prefs synchronize];
for (NXOAuth2Account *a in [[NXOAuth2AccountStore sharedStore] accounts] ){
[[NXOAuth2AccountStore sharedStore] removeAccount:a];
}
UINavigationController *navigationController = (UINavigationController *)self.window.rootViewController;
[navigationController popToRootViewControllerAnimated:YES];
}
I need to reinitialize all data in XYZMainViewController.
Thank you.
Look like problem is related to fetching JSON Object. It is possible that everytime you have send same user to fetch user data. You are not using NSUserdefault object to display name, you are using value, which is return by JSON Object. According to me cause of error is "withAccount:[XYZCommonFunctions user]" line.
I would like to suggest, instead of using
-(void)viewWillAppear:(BOOL)animated {
you can use
- (void)viewDidLoad
so that your login action performed only when your LoginController loads,instead when LoginController appear.
New viewwillAppear look as given below -
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self.navigationController setNavigationBarHidden:YES animated:NO];
[self.label setText:#""];
}
and ViewDidLoad -
- (void)viewDidLoad
{
[super viewDidLoad];
[self homeProfile];
}
Also check your json response, whether you are getting response success or error.According to response need to handle.
Hope this helps.
I am trying to copy the contents of one NSDictionary into a NSMutableDictionary.
This is what I have done so far.
#implementation RosterListController
- (void)newMessageReceived:(NSDictionary *)messageContent
{
self.messageDictionary = [[NSMutableDictionary alloc]initWithDictionary:messageContent]; // This is where I am copying
UIApplication *app = [UIApplication sharedApplication];
if (app.applicationState == UIApplicationStateActive)
{
UILocalNotification *localNotif = [[UILocalNotification alloc]init];
if (localNotif)
{
localNotif.alertAction = #"OK";
localNotif.applicationIconBadgeNumber = [[UIApplication sharedApplication] applicationIconBadgeNumber] + 1;
[app presentLocalNotificationNow:localNotif];
}
}
}
Then I handle this notification in appDelegate by showing a AlertView.After that is done..coming back to RosterViewController.
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 0) {
NSLog(#"Cancel button presed");
}
else
{
if(chatView) // Chat ViewController
{
[chatView recvdMsg:self.messageDictionary];
}
else
{
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"MainStoryboard"
bundle: nil];
chatView=(ChatViewController *)[mainStoryboard instantiateViewControllerWithIdentifier:#"chatviewcontroller"];
NSMutableDictionary *buddy=[[NSMutableDictionary alloc]init];
// The break point stops the app here & shows buddy dictionary as nil.
==> [buddy setObject:[self.messageDictionary objectForKey:#"sender"] forKey:#"jid"];
// Originally it was messageContent dict from the parameter above that I used which worked fine..
//But since I need that dictionary in another method..I copied that dictionary into self.messageDictionary which also gets copied.
// However now the above line causes problems.
// [buddy setObject:[self.messageContent objectForKey:#"sender"] forKey:#"jid"];
chatView.buddyData=buddy;
[self.navigationController pushViewController:chatView animated:YES];
[chatView recvdMsg:self.messageDictionary];
}
}
}
To create NSMutableDictionary from NSDictionary you should use dictionaryWithDictionary which is declared in NSDictionary.h.
NSMutableDictionary *aMutDictFromAnotherDictionary = [NSMutableDictionary dictionaryWithDictionary:YOUR_NSDICTIONARY_OBJECT];