After visiting a share url on a website, viewers are prompted to open the link in my application. If the application is running, it works perfectly.
However, if the application is closed, the viewDidLoad and viewWillAppear methods are not called on my ViewController, so I am not able to open the desired ViewController.
Does anyone know how to allow to get the viewDidLoad function to run if the app is launched from the openURL function?
I currently have:
AppDelegate:
-(BOOL) application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
if (!url) { return NO; }
NSString *party_url = [NSString stringWithFormat:#"%#%#/", PARTYURL, url.lastPathComponent];
[[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:#"WebViewNotification" object:party_url]];
return YES;
}
ViewController:
- (void)viewDidLoad {
[super viewDidLoad];
appDelegate = [AppDelegate getDelegate];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(webViewNotification:) name:#"WebViewNotification" object:nil];
}
- (void)webViewNotification:(NSNotification *)notification {
NSString *url = [notification object];
PartyViewController *partyViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"PartyViewController"];
partyViewController.partyUrl = url;
[self.navigationController pushViewController:partyViewController animated:YES];
}
Again, this works fine if the app was previously opened. However, if it is closed, this does not work. Thank you!
When your app launched from a link without any other operation you don't have a presented ViewController contains this code in your views stacks. so this code will never been executed. consider directly present partyViewController in your CustomTabBarController.
Related
I add breakpoint and find that it block in the method that
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
// init local data
[[PDKeychainBindings sharedKeychainBindings] setObject:#"0" forKey:kNEED_GESTURE_LOGIN];
// register notification to notice switching RootVC
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(switchRootControllerWithType:)
name:kNoti_SwitchRootView
object:nil];
// init the third part SDK
[self setupShareSDK];
[self setupBugly];
[self setupUMeng];
[self setupIQKeyBoard];
[self setupZhugeIOWithOptions:launchOptions];
[self setupTrusfort];
// register push service
[self setupJPushWithOptions:launchOptions];
[self dealWithRemoteNotification:launchOptions];
// set local flag
[KXUserIntroManager setupFlag];
if (self.remoteNotification) {
if ([AccountStateManager isLogin])
[self.loginNavigationController showGesturePDViewController];
self.window.rootViewController = self.loginNavigationController;
} else {
self.window.rootViewController = self.launchController;
}
return YES;
}
i also try the way in stackOverFlow ,Add the following code to the above method
NSArray *args = [NSProcessInfo processInfo].arguments;
for(NSString *arg in args){
if ([arg isEqualToString:#"NoAnimations"]) {
[UIView setAnimationsEnabled:false];
}
}
Image link
it is the detail of didFinishLaunching method. it just init some data and create a notification
While this is not a direct answer to your question, it may well be that your issue is symptomatic of the very evident fact that you are doing much too much work, on the main thread, in didFinishLaunchingWithOptions. Your main job in this method is to get out of the way and let the runtime launch the app. You are doing the exact opposite of that.
I am facing this weird problem. I have a simple piece of code that is supposed to work fine but it doesn't work when first time launching the app. It works perfectly fine when I run the application second time.
And by the way the following code is used to open the application and display a viewController when i tap the today view widget:
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url
{
OverviewDetailVC *overViewDetail = (OverviewDetailVC *)initViewController;
overViewDetail.productDetail = [self.managedObjectContext executeFetchRequest:FetchRequest error:nil];
overViewDetail.productName = [overViewDetail.productDetail[0] valueForKey:#"generic"];
[self.window.rootViewController presentViewController:overViewDetail animated:YES completion:NULL];
}
Try this:
(BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url
{
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:#"secondshowPushNotification" object:nil];
});
}
FirstView controller:
(void)viewDidLoad
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(showCompanyFromPushNotification:) name:#"secondshowPushNotification" object:nil];
}
-(void)showCompanyFromPushNotification:(NSNotification*)notification
{
[self.rootController presentViewController:secondViewController animated:YES completion:nil];
}
// it open's secondViewController.
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"];
In UIViewController I register for UIApplicationWillEnterForegroundNotification notification.
-(void)viewDidAppear:(BOOL)animated {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(btnContinuePressed:)
name:UIApplicationWillEnterForegroundNotification
object:nil];
}
I want to execute btnContinuePressed: only if the application was resumed in a normal way - clicking the icon or opening via multitasking menu.
Method btnContinuePressed: should not be executed when the application was opened using URL scheme. Opening via URL scheme is handled in AppDelegate using custom notification:
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
[[NSNotificationCenter defaultCenter] postNotificationName:#"didOpenViaUrl"
object:url];
return YES;
}
Bottom line: notification UIApplicationWillEnterForegroundNotification should not be triggered if didOpenViaUrl was.
In simple word you can not make difference them but you can do a tricky way to achieve by creating a BOOL property in your appDelegate code which will tell you from where the application has been opened I think!
The notification I receive contains an url to open in a UIWebView. But I cannot access the UIWebview from my AppDelegate (this is where is receive the notification).
-(void) application:(UIApplication *)application didReceiveRemoteNotification(NSDictionary* ) userInfo{
// handle notification (this works)
//HERE I want to call my UIWebView and load the url I got.
}
One way to do this is to post a notification that your UIWebView receives. Check out the NSNotificationCenter Class Reference or this example on SO.
In my app I have used the following, this is when the UIWebView is already on the screen:
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
NSString *urlString = [userInfo objectForKey:#"url"];
if( [self.window.rootViewController isKindOfClass:[UINavigationController class]] ){
UINavigationController *currentNavigationController = (UINavigationController*)self.window.rootViewController;
if( [currentNavigationController.visibleViewController isKindOfClass:[NHCallVC class]] ){
SomeViewController *currentViewController = (SomeViewController*)currentNavigationController.visibleViewController;
[currentViewController.webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:urlString]]];
}
}
}
The structure with the UINavigationController seems complex, but this was needed for the way I set up my app. This can be different in your app.
The idea is to get the viewcontroller that is opened and load a URL on the UIWebView. The code is assuming the UIViewController with the UIWebView is currently open. The code should be altered if you want to navigate to the correct UIViewController before opening the url in the UIWebView.
Place an observer to the view where UIWebView resides such as:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(recievedNotification:) name:#"ReceivedNotification" object:nil];
Write the appropriate code within recievedNotification function which changes the UIWebView's target url.
And post a notification in didReceiveRemoteNotification function in APP Delegate such as:
[[NSNotificationCenter defaultCenter] postNotificationName:#"ReceivedNotification" object:nil];
Good luck.