When user open the app it show login UIViewController. When user log in it redirect to next mapkit UIViewController. But when user open app again I would like that he will skip login UIViewController. How can I do that? I tried programatically redirect in login method viewWillAppear but it works bad(It show controller for second).
A better way is to add this check in the AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
if(isLoggedin) {
Storyboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UIViewController *mapViewController = [storyboard instantiateViewControllerWithIdentifier:#"mapViewController" ];
self.rootViewController = [[UINavigationCotroller alloc] initWithRootViewController:mapViewController];
}
return YES;
}
Instead of checking the login in the viewWillAppear: method of the first view controller, do it in the didFinishLaunchingWithOptions: method of your application delegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
if (loggedIn) {
UINavigationController *navigationController = (UINavigationController *)self.window.rootViewController;
[navigationController.topViewController performSegueWithIdentifier:#"1to2" sender:navigationController.topViewController];
return YES;
}
}
where 1to2 is the identifier of the segue from view controller 1 to 2.
You can do it like this:
AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// replace with your real auth-checking
if ([self wasAuthorized] == NO) {
[self showLoginController];
}
return YES;
}
- (UIViewController *)mainController {
UINavigationController *rootNavigationController = (UINavigationController *)[[self window] rootViewController];
return [[rootNavigationController viewControllers] firstObject];
}
- (void)showLoginController {
UIViewController *loginController = [self loginController];
dispatch_async(dispatch_get_main_queue(), ^{
[self.mainController presentViewController:loginController animated:YES completion:nil];
});
}
- (UIViewController *)loginController {
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
return [mainStoryboard instantiateViewControllerWithIdentifier:#"LoginNavController"];
}
Related
AppDelegate.m
This works correct (show splash when app goes into the background)
- (void)applicationDidEnterBackground:(UIApplication *)application
{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"NativeScreens" bundle:nil];
SplashVC *SplashViewController=[storyboard instantiateViewControllerWithIdentifier:#"SplashVC"];
[self.window.rootViewController presentViewController:SplashViewController animated:NO completion:NULL];
}
But now I need to call this from the react-native.
I created a method with the same functionality:
RCT_EXPORT_METHOD(showCustomNativeSplashScreen)
{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"NativeScreens" bundle:nil];
SplashVC *SplashViewController=[storyboard instantiateViewControllerWithIdentifier:#"SplashVC"];
[self.window.rootViewController presentViewController:SplashViewController animated:NO completion:NULL];
}
It is available in RN, (Im see it from console.log) but when I call it - nothing happens.
import { NativeModules } from 'react-native';
...
console.log(NativeModules.AppDelegate); // Object{showCustomNativeSplashScreen: function}
NativeModules.AppDelegate.showCustomNativeSplashScreen(); // nothing :(
What am I doing wrong?
It was necessary to find the upper controller source
- (UIViewController *)topViewController{
return [self topViewController:[UIApplication sharedApplication].keyWindow.rootViewController];
}
- (UIViewController *)topViewController:(UIViewController *)rootViewController
{
if (rootViewController.presentedViewController == nil) {
return rootViewController;
}
if ([rootViewController.presentedViewController isMemberOfClass:[UINavigationController class]]) {
UINavigationController *navigationController = (UINavigationController *)rootViewController.presentedViewController;
UIViewController *lastViewController = [[navigationController viewControllers] lastObject];
return [self topViewController:lastViewController];
}
UIViewController *presentedViewController = (UIViewController *)rootViewController.presentedViewController;
return [self topViewController:presentedViewController];
}
RCT_EXPORT_METHOD(showCustomNativeSplashScreen)
{
self.lastTopVC = [self topViewController];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"NativeScreens" bundle:nil];
SplashVC *SplashViewController=[storyboard instantiateViewControllerWithIdentifier:#"SplashVC"];
[self.lastTopVC presentViewController:SplashViewController animated:NO completion:NULL];
}
I am recieving push notification from backend but unable to go to specific controller from the click of push notification.
My Code is:
In appDelegate.m:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSDictionary* payLoad = [[launchOptions objectForKey:#"UIApplicationLaunchOptionsRemoteNotificationKey"] objectForKey:#"appsInfo"];
if ([[payLoad objectForKey:#"type"] isEqual: #"COURSE_DISTRIBUTE"]){
UIViewController *loginController = [[UIStoryboard storyboardWithName:#"iphone_Storyboard" bundle:nil] instantiateViewControllerWithIdentifier:#"EPAnalyticsViewController"]; //or the homeController
UINavigationController *navController = [[UINavigationController alloc]initWithRootViewController:loginController];
self.window.rootViewController = navController;
// [self.window makeKeyAndVisible];
} else if ([[payLoad objectForKey:#"type"] isEqual: #"ASSESSMENT_DISTRIBUTE"]){
UIViewController *loginController = [[UIStoryboard storyboardWithName:#"iphone_Storyboard" bundle:nil] instantiateViewControllerWithIdentifier:#"OUSTCardsViewController"]; //or the homeController
UINavigationController *navController = [[UINavigationController alloc]initWithRootViewController:loginController];
self.window.rootViewController = navController;
//[self.window makeKeyAndVisible];
}
In didReceiveRemoteNotification method I have Written:
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
NSLog(#"didReceiveRemoteNotification");
if ([[payLoad objectForKey:#"type"] isEqual: #"COURSE_DISTRIBUTE"]){
UIViewController *loginController = [[UIStoryboard storyboardWithName:#"iphone_Storyboard" bundle:nil] instantiateViewControllerWithIdentifier:#"EPAnalyticsViewController"]; //or the homeController
UINavigationController *navController = [[UINavigationController alloc]initWithRootViewController:loginController];
self.window.rootViewController = navController;
// [self.window makeKeyAndVisible];
} else if ([[payLoad objectForKey:#"type"] isEqual: #"ASSESSMENT_DISTRIBUTE"]){
UIViewController *loginController = [[UIStoryboard storyboardWithName:#"iphone_Storyboard" bundle:nil] instantiateViewControllerWithIdentifier:#"OUSTCardsViewController"]; //or the homeController
UINavigationController *navController = [[UINavigationController alloc]initWithRootViewController:loginController];
self.window.rootViewController = navController;
//[self.window makeKeyAndVisible];
}
}
On - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions you should set the root view controller.
And then on - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo you should use pushViewController or performSegue.
For e.g. -
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
UIViewController *loginController = [[UIStoryboard storyboardWithName:#"iphone_Storyboard" bundle:nil] instantiateViewControllerWithIdentifier:#"EPAnalyticsViewController"];
self.window.rootViewController = navController;
}
And now when you receive notification -
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
if ([[payLoad objectForKey:#"type"] isEqual: #"COURSE_DISTRIBUTE"]){
UIViewController *viewController = [[UIStoryboard storyboardWithName:#"iphone_Storyboard" bundle:nil] instantiateViewControllerWithIdentifier:#"EPAnalyticsViewController"];
[self.navigationController pushViewController:viewController]
} else if ([[payLoad objectForKey:#"type"] isEqual: #"ASSESSMENT_DISTRIBUTE"]){
UIViewController * viewController = [[UIStoryboard storyboardWithName:#"iphone_Storyboard" bundle:nil] instantiateViewControllerWithIdentifier:#"OUSTCardsViewController"];
[self.navigationController pushViewController:viewController]
}
}
I have login and signup viewcontrollers in Login storyboard not in the Main storyboard.
Once signup or login is successful, then I am changing Login storyboard to Main. The following code works but when I select any tab, it does not call tab delegate method in the AppDelegate
However, if user is already succesfully signup or logged in, then it calls the following tabbar delegate method.
LoginViewController.m
if(isLoginSuccess)
{
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
CustomTabBarViewController *tbc = [mainStoryboard instantiateViewControllerWithIdentifier:#"tabbar"];
tbc.selectedIndex = 2;
[self presentViewController:tbc animated:YES completion:nil];
}
AppDeletage.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
CustomTabBarViewController *tabBarController = (CustomTabBarViewController *)self.window.rootViewController;
tabBarController.delegate = self;
return YES;
}
-(void) tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController
{
if (tabBarController.selectedIndex == 2) {
if(![self isRegistered])
{
UIStoryboard *loginStoryboard = [UIStoryboard storyboardWithName:#"LoginStoryboard" bundle:nil];
UIViewController *vc = [loginStoryboard instantiateViewControllerWithIdentifier:#"LoginViewController"];
[ROOTVIEW presentViewController:vc animated:YES completion:nil];
}
else
{
tabBarController.selectedIndex = 2;
}
}
}
Update :
AppDelegate is not getting called but I wonder why the following code does not open Loginstoryboard in the AppDelegate after user is logout.
#define ROOTVIEW [[[UIApplication sharedApplication] keyWindow] rootViewController]
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"LoginStoryboard" bundle:nil];
UIViewController *vc = [mainStoryboard instantiateViewControllerWithIdentifier:#"LoginViewController"];
[ROOTVIEW presentViewController:vc animated:YES completion:nil];
Please find below code.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
UIStoryboard *main = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UITabBarController *tabController = [main instantiateViewControllerWithIdentifier:#"TabbarController"];
tabController.delegate = self;
return YES;
}
-(void) tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController{
NSLog(#"Selected Index - %lu",(unsigned long)tabBarController.selectedIndex);
}
On ViewController's Button Click Method,
- (IBAction)btnLoginTapped:(id)sender {
UIStoryboard *main = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UITabBarController *tabController = [main instantiateViewControllerWithIdentifier:#"TabbarController"];
tabController.selectedIndex = 1;
[self presentViewController:tabController animated:YES completion:nil];
}
then on Main.storyboard, Drag Object from the Object Library and put it below First Responder in Tab bar Controller Scene, Set the Object class to AppDelegate, then right click on Tab Bar Controller and set delegate to that Object Class as shown in below image.
Let me know it is working or not, I'm ready to help with the solution.
I'm trying to select which ViewController the AppDelegate should display based in a NSUserDefaults BOOL. But the HomeViewController does not display.
I'm using Storyboards and I have my own class of UINavigationController.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[FBLoginView class];
[FBProfilePictureView class];
MeuNavigationController *nav = [[MeuNavigationController alloc]init];
if ([NSUD boolForChave:#"firstLogin"]==false) {
ViewController *viewC = [[ViewController alloc]init];
[nav pushViewController:viewC animated:NO];
}else{
HomeViewController *viewP = [[HomeViewController alloc]init];
[nav pushViewController:viewP animated:NO];
}
return YES;
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[FBLoginView class];
[FBProfilePictureView class];
UIViewController *controller = nil;
if ([NSUD boolForChave:#"firstLogin"]==false) {
controller = [[ViewController alloc]init];
}else{
controller = [[HomeViewController alloc]init];
}
self.window.rootViewController = [[MenuNavigationController alloc] initWithRootViewController:controller];
[self.window makeKeyAndVisible];
return YES;
}
You noted that you're doing this off of storyboard. You might want to consider making this change as well:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[FBLoginView class];
[FBProfilePictureView class];
// Name of storyboard
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UIViewController *controller = nil;
if ([NSUD boolForChave:#"firstLogin"]==false) {
controller = [[ViewController alloc]init];
// Set this in the storyboard's identity inspector
controller = [storyboard instantiateViewControllerWithIdentifier:#"ViewController"];
}else{
controller = [storyboard instantiateViewControllerWithIdentifier:#"HomeViewController"];
}
self.window.rootViewController = [[MenuNavigationController alloc] initWithRootViewController:controller];
[self.window makeKeyAndVisible];
return YES;
}
But you ask... Mr. jakenberg, how does one set their unique view controller identifier?
Cheers
I have 2 ViewController. loginViewControl which sets to rootViewControoler :
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
loginViewControl = [[LoginTab alloc] init];
self.window.rootViewController = loginViewControl;
[self.window makeKeyAndVisible];
return YES;
}
And I create StatusViewController :
*.h
#interface StatusViewController : UIViewController<UITabBarControllerDelegate>
{
IBOutlet UITabBarController *tabBarController;
IBOutlet UIButton *UploadButton;
IBOutlet UIButton *ConvertorButton;
IBOutlet UIButton *CompletedButton;
}
#property (nonatomic, retain) IBOutlet UITabBarController *tabBarController;
#end
Now I want to push StatusViewController from loginViewControl(rootviewcontroller).I used below code but it not work.
- (IBAction)statusButtonClick:(id)sender;
{
StatusViewController *statusView = [[StatusViewController alloc]init];
[self.navigationController pushViewController:statusView animated:YES];
[statusView release];
}
Do you have any suggestions? Thanks in advance
You not setting UINavigationViewcontroller at the didFinishLaunchingWithOptions of Window's RootViewcontroller, We can't Push a UIViewController without UINavigationViewcontroller
So First Set LoginViewController as a RootViewController of UINavigationViewcontroller like Bellow:-
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
loginViewControl = [[YourLoinViewcontroller alloc] initWithNibName:#"YourLoinViewcontroller" bundle:nil];
UINavigationController *objNavigationController=[[UINavigationController alloc]initWithRootViewController:loginViewControl];
self.window.rootViewController = objNavigationController;
[self.window makeKeyAndVisible];
return YES;
}
EDIT
Connect your StatusViewcontroller's view with File owner like bellow:-
your push method like this:-
- (IBAction)statusButtonClick:(id)sender;
{
StatusViewController *statusView = [[StatusViewController alloc]initWithNibName:#"StatusViewController" bundle:nil];
[self.navigationController pushViewController:statusView animated:YES];
}
Unless your login view controller is a navigation controller, self.navigationController in statusButtonClick will return nil and so this won't work.
Maybe you can try:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
loginViewControl = [[LoginTab alloc] init];
self.window.rootViewController = [[UINavigationController alloc] initWithRootViewController:loginViewControl];
[self.window makeKeyAndVisible];
return YES;
}
This will enclose a loginViewController in a navigationController which will permit you to push another viewController in the navigationController's stack.
- (IBAction)statusButtonClick:(id)sender; {
// If used StoryBoard
UIStoryboard *story=[UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
StatusViewController *statusView = [story instantiateViewControllerWithIdentifier:#"StatusViewController"];
[self.navigationController pushViewController:statusView animated:YES];
// If used XIB
StatusViewController *statusView = [[StatusViewController alloc]initWithNibName:#"StatusViewController" bundle:nil];
[self.navigationController pushViewController:statusView animated:YES]; }