I have some problems with NSNotificationCenter and didReceiveRemoteNotification. I want to open my ViewController when i receive new notification from APNS. Inside body notification i have objectId - it's key.
I try to open my ViewController into didReceiveRemoteNotification but it's not working ((
AppDelegate.m
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
[[NSNotificationCenter defaultCenter]
postNotificationName:kDidReceiveRemoteNotification
object:userInfo];
}
NewsDetailViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:#selector(didReceiveRemoteNotification:)
name:kDidReceiveRemoteNotification
object:nil];
}
- (void)didReceiveRemoteNotification:(NSNotification *)notification
{
NSLog(#"%s %#",__func__,[notification.userInfo description]);
}
Const.h
#define kDidReceiveRemoteNotification #"UIApplicationDidReceiveRemoteNotification"
ViewController not loaded. i dont know what to do.
The current flow of the sample code you've attached is:
When receiving push notification, post a notification to NSNotificationCenter (something completely different and unrelated to push notifications).
When another view is loaded (someone needed to load this view before the push notification was received), subscribe to this NSNotificationCenter notification.
When the notification is posted, print it to log.
It was hard for me to understand this from your question, but if the view controller you're trying to launch as a result of receiving the push notification is NewsDetailViewController, then your code doesn't do that. What you're code does is prints out the notification to log (assuming that somebody else made sure that NewsDetailViewController is loaded before the push notification was received).
In order to load the NewsDetailViewController when the push notification is received, you don't need to post the notification to NSNotification
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
NewsDetailViewController *newsVC = [[NewsDetailViewController alloc] initWithNibName:#"NewsDetailViewController" bundle:nil];
[self.window.rootViewController.view addSubview:newsVC.view];
}
Or any other loading logic that works better for you. But in the current code you posted, there is no connection between receiving the push notification and loading the ViewController.
I hope this helps. Good luck!
Related
I need to show a universal custom view whenever i received a notification in a active app.
I have created a view , but i am not getting how to show that!
Can anyone help me out.
You have to handle the notification in the AppDelegate methods (usually application(_:didReceiveRemoteNotification:fetchCompletionHandler:)) and launch the view in the form it can be shown in any screen of your app.
You can read the docs for UIApplicationDelegate here, section Responding to Notifications and Events.
You will be receiving the push notification in AppDelegate's application(_:didReceiveRemoteNotification:fetchCompletionHandler:) from here you can handle.
- (void)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))handler
{
// 1. You can call your universal view from here
OR
// 2. You can post this local notification with information
NSDictionary *userInfo = [NSDictionary dictionaryWithObject:myObject forKey:#"info"];
[[NSNotificationCenter defaultCenter] postNotificationName:#"showNotification"
object:nil
userInfo:userInfo];
}
For 2nd Option, you will need add observer and receiving method:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(receiveNotification:)
name:#"showNotification"
object:nil];
-(void)receiveNotification:(NSNotification *)notification {
// call your view
}
I have implemented everything correctly in my app to receive push notifications, i'm receiving the notifications just fine, but how can i do something when the user clicks on it?
Here's my code regarding the matter:
AppDelegate.m:
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
NSLog(#"Received notification: %#", userInfo);
NSLog(#"Hello from appDelegate");
}
It's working, i'm getting the userInfo and the other message in my Xcode log.
Now i want to do something (go to a specific segue) when the user clicks on the notification. I have seen the docs but it's very complicated and hard to follow.
I just need to know what function to use in the MainViewController.m
Any hints? thanks in advance.
You can post notifications (Using NSNotificationCenter) from AppDelegate on different events and then add observer in particular classes where ever you want to perform a particular operation.
Code Implementation
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo{
NSString *aStrEventType = userInfo[#"eventType"];
if ([aStrEventType isEqualToString:#"callWebService"]) {
[[NSNotificationCenter defaultCenter] postNotificationName:#"callWebService" object:nil];
}else{
// Implement other notification here
}
}
Now in your particular class you can handle notification as follows.
- (void)viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:#"" selector:#selector(callMyWebService) name:nil object:nil];
}
-(void)callMyWebService{
//Perform your action.
}
In a nut shell, I have three views: Main View, List View (to display the buddies list) and Chat View(where you chat).
The push notification is correctly setup in this app, so I have no problems in receiving the push notification payload, my question lies on why in a specific scenario the received message seemed lost and doesn't appear in Chat View
I have a strange problem, so please carry on read the whole description:
So here I put some code to show how I handle the push notifications:
In AppDelegate.m
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
// Extract the Sinch-specific payload from the Apple Remote Push Notification
NSString* payload = [userInfo objectForKey:#"SIN"];
[self initSinchClientWithUserId:userid];
// Get previously initiated Sinch client
id<SINNotificationResult> result = [_client relayRemotePushNotificationPayload:payload];
if ([result isMessage]) {
// Present alert notifying
NSString *messageId = [[result messageResult] messageId];
NSLog(#"Received messageid: %#", messageId);
if([UIApplication sharedApplication].applicationState == UIApplicationStateBackground ||
[UIApplication sharedApplication].applicationState == UIApplicationStateInactive) {
self.messageSenderId = [[result messageResult] senderId];
[[NSNotificationCenter defaultCenter] postNotificationName:#"ReceivedRemoteNotification" object:self userInfo:nil];
NSLog(#"handle remote notification in modal");
} else {
self.messageSenderId = [[result messageResult] senderId];
// this will launch a modal of private chat, so better to invoke this when running in background
[[NSNotificationCenter defaultCenter] postNotificationName:#"SetUnreadIcon" object:self userInfo:nil];
NSLog(#"handle remote notification by marking icons");
}
} else if (![result isValid]) {
// Handle error
}
NSLog(#"Received Payload: %#", payload);
}
In Main View, handles ReceivedRemoteNotification and SetUnreadIcon
-(void) viewDidLoad {
[super viewDidLoad];
....
// setup a local notification handler
NSNotificationCenter *notifCentre = [NSNotificationCenter defaultCenter];
[notifCentre addObserver:self selector:#selector(invokeRemoteNotifications:) name:#"ReceivedRemoteNotification" object:nil];
[notifCentre addObserver:self selector:#selector(setUnreadIcon:) name:#"SetUnreadIcon" object:nil];
....
}
- (void)invokeRemoteNotifications: (NSNotification *) notification {
shouldDismiss = NO;
[self invokeNotifications];
}
- (void)invokeNotifications {
[self performSegueWithIdentifier:#"modalToChat" sender:self];
}
- (void)setUnreadIcon: (NSNotification *) notification {
AudioServicesPlaySystemSound (1300);
shouldDismiss = YES;
[self.rightbutton setCustomView:notifyButton];
}
When user tap rightbutton in MainView, will call up the ListView.
In ChatView, it implements SINMessageClientDelegate delegate methods (See Documentation), namely
– messageClient:didReceiveIncomingMessage:
– messageSent:recipientId:
– messageDelivered:
– messageFailed:info:
– message:shouldSendPushNotifications:
The Working Scenario
Assume user Alice send message to Bob. Bob received this message via push notification. So Bob open and tap the notifications, the app will show up and automatically showing a modal view of ChatView.
In this case, the message from the push notifications can be displayed in Chat View
The Not Working Scenario
Assume user Alice send msg to Bob again, this time Bob received the notification while the app is in foreground. So this method will be executed:
- (void)setUnreadIcon: (NSNotification *) notification {
AudioServicesPlaySystemSound (1300);
shouldDismiss = YES;
[self.rightbutton setCustomView:notifyButton];
}
Then Bob will tap rightbutton to call up ListView, find Alice and open the conversation. Bob will find that the message just received from Alice is not displayed in ChatView
Questions
In Sinch SDK, there seemed no approach to manually retrieve the messages even the messageId is retrieved while receiving the push notification. Am I correct?
In the "Not Working" case, why the message is lost? If the sinch client is responsible for relaying the messages, what reason to make it discard the messages?
Still in the "Not Working" case, how I can persist the messages, and then later display it? Must I implement the SINMessageClientDelegate elsewhere?
Thanks,
Regarding your first question, there is no way to query for a particular message in that way you are describing.
The problem for your "Not Working"-case is likely that by the time the Sinch SDK fetches the instant message and is about to notify the message client delegate, your Chat View has not yet been instantiated / assigned to be the delegate, and because of that the message is "missed" by the delegate.
I would recommend you to have a non-ViewController component implement the SINMessageClientDelegate, and make that component have a life-cycle that is independent of your view controllers. I.e. have the component acting as the delegate be created at application launch, and keep it alive. Then you can be sure to always receive all onIncomingMessage:, and you can also place logic for persisting messages there.
In my app, there's a collection view displaying a set of images retrieved from a web service. Each image has tags. So the app has the ability to filter images using tags as well.
Now I'm trying to add push notifications to this app. A push notification is sent when new images have been added to the server. These images are tagged say, latest. I'm passing that tag as the message via a push notification and what I need is when the user taps on the push notification to open the app, it should load the latest new images to the collection view.
I'm half way done. I receive the push notification with the message successfully to the didReceiveRemoteNotification method in the AppDelegate.m file. Now I need to pass it on to the view controller where the collection view is. I'm stuck at this point. I can't figure out how to send it over to the view controller.
I tried declaring a property in the App delegate, assign the message value to it and referring it from the view controller but it didn't work. I tied delegates, notification center, user defaults but nothing worked.
Can anyone please tell me how to accomplish this?
Thank you.
Edit:
Here's my code. The last method I tried was the local notifications.
AppDelegate.m
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
[[NSNotificationCenter defaultCenter] postNotificationName:#"PushNotificationMessageReceivedNotification" object:nil userInfo:userInfo];
}
ViewController.m
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(remoteNotificationReceived:) name:#"PushNotificationMessageReceivedNotification"
object:nil];
}
- (void)remoteNotificationReceived:(NSNotification *)notification
{
NSLog(#"Notification: %#", notification.userInfo);
NSString *msg = [[notification.userInfo valueForKey:#"aps"] valueForKey:#"alert"];
self.label.text = msg;
}
Case 1: if your app is background and user launches app with notification click then you have the check if app launched form notification or normal
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
NSDictionary *remoteNotificationPayload = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
if (remoteNotificationPayload) {
[[NSNotificationCenter defaultCenter] postNotificationName:#"notification" object:nil userInfo:remoteNotificationPayload];
}
return YES; }
Case2: If your app is in forground notification will be received in didReceiveRemoteNotification
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
NSLog(#"userinfo %#",userInfo);
[[NSNotificationCenter defaultCenter] postNotificationName:#"notification" object:nil userInfo:userInfo];
}
Now you and add a observer in any controller with Local notification and do what you wand to do
I don't know it will work or not,its only my suggestion. I did't tried it before but in your case may be it work
user NSUserDefaults for this.
in your appDelegate.m
[[NSUserDefaults standardUserDefaults] setObject:imageArrayFromServer forKey:#"MyAppSpecificGloballyUniqueString"];
in your viewController.m
NSArray *myArray = [[NSUserDefaults standardUserDefaults] objectForKey:#"MyAppSpecificGloballyUniqueString"];
Is it possible to open concrete viewcontroller when user tap on push notification?
I have news app, main view controller have a lot of news, and when user tap on some new I open next viewcontroller with description of this news.
When user tap push notification, how I can open second view controller?
I tried to send Notification to my UINavigationController and push two controllers, but it doesn't work fine, it open only first viewcontroller.
you can handle your app, when you tap a local or push notification, implementing the application:didReceiveLocalNotification: or application: didReceiveRemoteNotification: method in your AppDelegate.m
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
}
-(void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
}
If your app it's closed (not in background) you can verify if you received a notification in
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSDictionary *userInfo = [launchOptions objectForKey: UIApplicationLaunchOptionsRemoteNotificationKey];
if ( userInfo != nil )
[self application:application didReceiveRemoteNotification:userInfo];
}
I don't know how you are handling your news but you can post a notification to your main view controller informing that you have receive a notification, passing the "id" or the info of your new and then create your second view controller (you will need to verify if your MainViewController is already created in the stack of your NavigationController):
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
[[NSNotificationCenter defaultCenter] postNotificationName:#"IHaveReceivedANotification" object:nil userInfo:userInfo];
}