I am just beginning to learn how to implement Push notifications with iOS and Parse.
At the moment, I can send push notifications from the Parse dashboard to the app,the notification is received, as I can see in the Xcode console, but now my issue is that I am not able to open a view controller from the AppDelegate.
This is my code:
- (void)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))handler {
// Create empty photo object
NSString *photoId = [userInfo objectForKey:#"p"];
NSLog(#"P=%#",photoId);
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"Main" bundle: nil];
Aceptado *targetViewController = (Aceptado*)[mainStoryboard instantiateViewControllerWithIdentifier:#"servicio_aceptado"];
UINavigationController *controlador = [[UINavigationController alloc]init];
[controlador pushViewController:targetViewController animated:YES];
}
As I said, the console show the log NSLog(#"P=%#",photoId) , the notification is received, but the view controller is not shown, any warning or error is shown.
Any help is welcome.
I have solved my problem like this:
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"Main"
bundle: nil];
Aceptado *controller = (Aceptado*)[mainStoryboard
instantiateViewControllerWithIdentifier: #"servicio_aceptado"];
controller.id_not =_id_not;
controller.idemployee = _idemployee;
controller.fullname = _fullname;
controller.phone = _phone;
controller.photo = _photo;
controller.dni = _dni;
controller.licenseplate = _licenseplate;
controller.model = _model;
controller.color = _color;
controller.latitude = _latitude;
controller.longitude = _longitude;
self.window.rootViewController = controller;
Now I can pass values to the target view controller from the AppDelegate file, keeping the SWRevealViewController structure.
Thank to all of you for your proposals.
try this code.
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"Main" bundle: nil];
Aceptado *targetViewController = (Aceptado*)[mainStoryboard instantiateViewControllerWithIdentifier:#"servicio_aceptado"];
UINavigationController *navVc=(UINavigationController *) self.window.rootViewController;
[navVc pushViewController: targetViewController animated:YES];
may help you.
Try this once.
UIStoryboard *storyBoard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
Slider1ViewController *viewcontroller = [storyBoard instantiateViewControllerWithIdentifier:#"Slider1ViewController"];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:viewcontroller];
[navController setViewControllers: #[viewcontroller] animated: YES];
[self.revealViewController setFrontViewController:navController];
[self.revealViewController setFrontViewPosition: FrontViewPositionLeft animated: YES];
You should not create new NavigationController, but use one existing. Usually it is rootViewController property of your key window.
Try this:
UINavigationController *controlador = self.window.rootViewController;
If you want to display your targetViewController in SWRevealViewController you may change your code as this:
SWRevealViewController *controlador = (SWRevealViewController)self.window.rootViewController;
[controloador pushFrontViewController:targetViewController animated:YES];
If you need display targetViewController over SWRevealViewController, use this:
WRevealViewController *controlador = (SWRevealViewController)self.window.rootViewController;
[controloador presentViewController:targetViewController
animated:YES
completion:nil];
If you need just replace SWRevealViewController with targetViewController use this:
self.window.rootviewController=targetViewController;
But don't forget save your SWRevealViewController in some another property.
Try this:
SomePageViewController *someVC = [self.storyboard instantiateViewControllerWithIdentifier:#"SomeVC"];
self.navController = [[UINavigationController alloc] initWithRootViewController:someVC];
self.window.rootViewController = self.navController;
[self.window makeKeyAndVisible];
If you want to push a view controller into navigation stack from appDelegate you need to cast your rootView controller as UINavigation Controller
Related
I want to navigate to specific Class when Click on Notification in Notification bar and after that in that particular class if I click back button I need to Navigate to previous according to requirement.
Can anyone please help.
I have added ViewController to Stack this way
(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"Main" bundle: nil];
SplashViewController *splashViewCon = (SplashViewController *)[mainStoryboard instantiateViewControllerWithIdentifier: #"SplashId"];
AgreeViewController *agreeViewCon = (AgreeViewController *)[mainStoryboard instantiateViewControllerWithIdentifier: #"agreeView"];
ViewController *loginViewCon = (ViewController *)[mainStoryboard instantiateViewControllerWithIdentifier: #"loginView"];
LanguageViewController *languageViewCon = (LanguageViewController *)[mainStoryboard instantiateViewControllerWithIdentifier: #"languageView"];
LandingScreenViewController *landingViewCon = (LandingScreenViewController *)[mainStoryboard instantiateViewControllerWithIdentifier: #"landingScreenId"];
HomeScreenViewController *homeViewCon = (HomeScreenViewController *)[mainStoryboard instantiateViewControllerWithIdentifier: #"homeScreen"];
OrderConfirmationViewController *orderconfirmViewCon = (OrderConfirmationViewController *)[mainStoryboard instantiateViewControllerWithIdentifier: #"orderConfirmationVC"];
ThankYouViewController *thankViewCon = (ThankYouViewController *)[mainStoryboard instantiateViewControllerWithIdentifier: #"ThankyouId"];
UploadQueueScreenViewController *uploadViewCon = (UploadQueueScreenViewController *)[mainStoryboard instantiateViewControllerWithIdentifier: #"uploadQueue"];
NewOrderViewController *newOrderViewCon = (NewOrderViewController *)[mainStoryboard instantiateViewControllerWithIdentifier: #"neworderView"];
MessageViewController *msgViewCon = (MessageViewController *)[mainStoryboard instantiateViewControllerWithIdentifier: #"MessageInboxscreen"];
MessageDetailsViewController *msgdetailsViewCon = (MessageDetailsViewController *)[mainStoryboard instantiateViewControllerWithIdentifier: #"msgDetailsView"];
NSArray *stack = [NSArray arrayWithObjects:splashViewCon,agreeViewCon,loginViewCon,languageViewCon,landingViewCon,homeViewCon,orderconfirmViewCon,thankViewCon,uploadViewCon,newOrderViewCon,msgViewCon,msgdetailsViewCon, nil];
navController.viewControllers = stack;
UILocalNotification *notification = [launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey];
if (notification)
{
MessageDetailsViewController *msgdetailsViewCon = (MessageDetailsViewController *)[mainStoryboard instantiateViewControllerWithIdentifier: #"msgDetailsView"];
self.window.rootViewController = msgdetailsViewCon;
}
}
So ,I want pop back to specific viewController
Find your viewcontroller in stack and pop it. This code may be help you find it.
for (YourViewController *controller in self.navigationController.viewControllers)
{
if ([controller isKindOfClass:[YourViewController class]])
{
[self.navigationController popViewController:controller animated:YES];
break;
}
}
As far as I know there is no generic class avaialbe. Try using the NSMutableArray, add via addObject and get first/last via objectAtIndex and removeObjectAtIndex.
You might wan to implement your own code to use those as a Stack.
Cheers :)
I have tried many code in my didReceiveRemoteNotification function in appdelegate.m
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
//Code
}
but didn`t work as expected.
With this code, doesn`t navigate to my profile view controller after I click the notification:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
ProfileViewController *controller = [storyboard instantiateViewControllerWithIdentifier:#"profileIdentifier"];
controller.userID = #"123";
controller.userName = #"calvinsug";
UINavigationController *navigationController = (UINavigationController *)self.window.rootViewController;
[navigationController pushViewController:controller animated:YES];
I have tried this also but didn`t navigate to the profile controller
[self.window.rootViewController presentViewController:controller animated:YES completion:NULL];
Finally, I try this code, but it is weird because it doesn't have back button (I think the cause is the profile controller become the initial view).
self.window = [[UIWindow alloc]
initWithFrame:UIScreen.mainScreen.bounds];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
ProfileViewController *controller = [storyboard instantiateViewControllerWithIdentifier:#"profileIdentifier"];
controller.userID = #"123";
controller.userName = #"calvinsug";
self.window.rootViewController = controller;
[self.window makeKeyAndVisible];
Any one have solution?
edit:
I think we can not set our target View controller to become a Root View Controller, because when we click notifications in other apps, we go to main screen first, then go to the specific view controller immediately
Try this:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
ProfileViewController *controller = [storyboard instantiateViewControllerWithIdentifier:#"profileIdentifier"];
controller.userID = #"123";
controller.userName = #"calvinsug";
UINavigationController *navController = [[UINavigationController alloc]initWithRootViewController:controller];
self.window.rootViewController = navController;
`
I am using SWRevealViewController in my project, and I want to open a particular controller when the app receives a notification. I have tried so many solutions but nothing works.
I follow this http://www.appcoda.com/ios-programming-sidebar-navigation-menu/ by using storyboard. My storyboard is designed as below:
When the application receives a notification I want to load Photo view controller within its navigation controller. I tried with the following code in the AppDelegate:
UIStoryboard *st = [UIStoryboard storyboardWithName:#"Main" bundle: nil];
photoViewController *descController = (PhotoViewController*)[st instantiateViewControllerWithIdentifier: #"photoView"];
UINavigationController *frontNavigationController = [[UINavigationController alloc] initWithRootViewController:descController];
SidebarTableViewController *rearViewController = (SidebarTableViewController*)[st instantiateViewControllerWithIdentifier: #"menuController"];
SWRevealViewController *mainRevealController = [[SWRevealViewController alloc] init];
mainRevealController.rearViewController = rearViewController;
mainRevealController.frontViewController= frontNavigationController;
self.window.rootViewController =nil;
self.window.rootViewController = mainRevealController;
[self.window makeKeyAndVisible];
This works, but creates a new Navigtion controller, and what I need is to use the one already defined in the storyboard, since it has specific properties.
Any idea?
Thanks
actually SwLRevalViewController Taken the ownership of Root, so do like this
in Appdelegate.m
//initially navigate to your Main controller on SWL
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler
{
NSString *alert = userInfo[#"aps"][#"redirect_url"];
[[NSUserDefaults standardUserDefaults]setObject:alert forKey:#"itemType"];
[[NSUserDefaults standardUserDefaults]synchronize];
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"Main" bundle: nil];
SWRevealViewController *main = (SWRevealViewController *)[mainStoryboard instantiateViewControllerWithIdentifier:#"SWRevealViewController"];
self.window.rootViewController = main;
}
//it automatically redirect to your root controller
on that main view controller ViewDidLoad check / Navigate to your photo view controller
NSString *getType=[[NSUserDefaults standardUserDefaults]objectForKey:#"itemType"];
if ([gettypeofItem isEqualToString:#"something"])
{
yourPhotoViewController *ivc=[self.storyboard instantiateViewControllerWithIdentifier:#"yourPhotoViewController"];
[self.navigationController pushViewController:ivc animated:YES];
}
else
{
// do nothing
}
You can use following method
NSString *storyBoardName=#"Main_iPad";
if (isPhone)
storyBoardName=#"Main_iPhone";
UIStoryboard *storyBoard=[UIStoryboard storyboardWithName:storyBoardName bundle:nil];
PlayVideoBySocketsScene *controller=[storyBoard instantiateViewControllerWithIdentifier:#"playVideoUsingSockets"];
float disptachTime=2.0;
if (value)
{
disptachTime=1.0;
}
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(disptachTime * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[[[[UIApplication sharedApplication] keyWindow] rootViewController] presentViewController:controller animated:YES completion:nil];
please try this it may help you. in this when you click on notification this method us called first insted for appdelegate
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
UINavigationController *navController = (UINavigationController *)self.window.rootViewController;
NotificationViewController *notificationViewController = [[NotificationViewController alloc] init];
[navController.visibleViewController.navigationController pushViewController:notificationViewController];
}
I have a sidebar menu, made with SWRevealViewController.
One of menu elements in sidebar is "sign-in". It opens sign-in view (via custom SWRevealViewController segue).
I want to programmatically switch to another view after user successfully signs in. How do I do that?
UPDATE, my code:
ViewController *vc = [[ViewController alloc] init]; // this is main front ViewController
SWRevealViewController *revealController = self.revealViewController;
[revealController setFrontViewController:vc animated:YES];
After this I get just empty screen. What am I doing wrong? I feel that this is wrong:
ViewController *vc = [[ViewController alloc] init];
so what is correct way to access already loaded view controller? (it loads at app start by SWRevealViewController as front controller)
Try this:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
SecondViewController *rootViewController = [storyboard instantiateViewControllerWithIdentifier:#"SecondViewController"];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:rootViewController];
[navController setViewControllers: #[rootViewController] animated: YES];
[self.revealViewController setFrontViewController:navController];
[self.revealViewController setFrontViewPosition: FrontViewPositionLeft animated: YES];
work for me :-)
Use
- (void)setFrontViewController:(UIViewController *)frontViewController animated:(BOOL)animated; method
SWRevealController has it's own property you can access from any UIViewController:
SWRevealViewController *revealController = self.revealViewController;
You can check example projects at it's GitHub repository:
https://github.com/John-Lluch/SWRevealViewController
Here is a Swift version of the setFrontViewController solution:
if let secondViewController = self.storyboard?.instantiateViewControllerWithIdentifier("SecondViewControllerStoryBoardID") as? SecondViewController {
let navController = UINavigationController(rootViewController: secondViewController)
navController.setViewControllers([secondViewController], animated:true)
self.revealViewController().setFrontViewController(navController, animated: true)
}
Try this:
ViewController *vc = [[ViewController alloc] init]; // this is main front ViewController
UINavigationController* navController = (UINavigationController*)self.revealViewController.frontViewController;
[navController setViewControllers: #[vc] animated: YES];
// [navController pushViewController:vc animated:YES]; // use this if you want to stack the views
[self.revealViewController setFrontViewPosition: FrontViewPositionLeft animated: YES];
There is a new API - (void)pushFrontViewController:(UIViewController *)frontViewController animated:(BOOL)animated;
As far as I know, this is the most elegant way that animates correctly to switch between view controllers manually.
// get the view controller you want to push to properly.
// in this case, I get it from Main.storyboard
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UIViewController * vc = [sb instantiateViewControllerWithIdentifier:#"SignInViewController"];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:vc];
[navController setViewControllers: #[vc] animated:NO];
[self.revealViewController pushFrontViewController:navController animated:YES];
If you are in the target vc that doesn't import SWRevealViewController and want to push back:
// get your vc properly
[self.navigationController setViewControllers:#[vc] animated:YES];
Please notice that [self.navigationController showViewController:vc sender:self]; has the same result, but don't use this since this creates a new view controller on the navigation stack, which is basically meaningless while using SWRevealViewController.
This one works for me perfectly
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
ViewController *rootViewController = [storyboard instantiateViewControllerWithIdentifier:#"ViewController"];
UINavigationController *navController = [storyboard instantiateViewControllerWithIdentifier:#"NavController"];
[navController setViewControllers: #[rootViewController] animated: YES];
[self.revealViewController setFrontViewController:navController];
[self.revealViewController setFrontViewPosition: FrontViewPositionLeft animated: YES];
#Evana has a good answer, however for my case which passing parameter to the destViewController, I need to improve it as below. By following her example exactly, I noticed the DestViewController viewDidLoad was called twice. First with 0 on the 'selectedId', only the second call did the 'selectedId' is receiving my tag value.
Thus, in order for a cleaner navigation, the DestViewController must be obtained from the navController, so that there is no redundant call.
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UINavigationController *navController = [storyboard instantiateViewControllerWithIdentifier:#"DestNavController"];
DestViewController *destViewController = (DestViewController*)[[navController viewControllers] objectAtIndex:0];
destViewController.selectedId = ((UIButton*)sender).tag;
[self.revealViewController setFrontViewController:navController];
I am currently using ViewDeck with Storyboards, and have the following setup in the application didFinishLaunchingWithOptions:
//View Deck Setup
UIStoryboard* mainStoryboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle: nil];
UIViewController* menuController = [mainStoryboard instantiateViewControllerWithIdentifier:#"LeftSideMenu"];
UINavigationController* navigationController = (UINavigationController *) self.window.rootViewController;
self.viewDeckController = [[IIViewDeckController alloc] initWithCenterViewController:navigationController leftViewController:menuController rightViewController:nil];
self.window.rootViewController = self.viewDeckController;
However, when I am setting a new CenterController from my MenuViewController, the navigation bar is removed, even if loading the same center view controller as I was previously looking at.
- (IBAction)viewUsers:(UIButton *)sender
{
UIStoryboard* mainStoryboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle: nil];
UIViewController* viewController = [mainStoryboard instantiateViewControllerWithIdentifier:#"middleViewController"];
[self.viewDeckController setCenterController:viewController];
[self.viewDeckController closeLeftView];
}
What am I doing incorrectly?
The solution is remove any "deck constructor" class between AppDelegate and you TabBar. When you need to set or change Deck structure I create a several methods for each one structure. For example, if you want Deck has "leftView" view controller in left side, "rightView" in the right and "tabBarHome" in center, create a method like this in App Delegate:
-(void) lanzarHome{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
IIViewDeckController* deckController =[[IIViewDeckController alloc] initWithCenterViewController:[storyboard instantiateViewControllerWithIdentifier:#"tabBarHome"]
leftViewController:[storyboard instantiateViewControllerWithIdentifier:#"leftView"]
rightViewController:[storyboard instantiateViewControllerWithIdentifier:#"rightView"]];
deckController.leftSize = 100;
self.window.rootViewController = deckController;
[self.window makeKeyAndVisible];
}
Now, you must call this method from your viewController with sentence like this:
[((VKAppDelegate*) [[UIApplication sharedApplication] delegate]) lanzarHome];
The most important think is that create the method that changes or inits Deck structure from AppDelegate and never you have another class or viewController between delegate and center TabBar.
I hope this answer solve your issue. For me was a very hard work to find out this issue.