Error in Switching views due to AppDelegate method - ipad

This is what i am doing in my application:
in my appDelegate.m file ,
//Four Views
#synthesize fvc;
#synthesize svc;
#synthesize tvc;
#synthesize pvc;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions: (NSDictionary *)launchOptions
{
NSString *name1,*name2,*name3;
name1 = NSLocalizedString(#"home", nil);
name2 = NSLocalizedString(#"quote", nil);
name3 = NSLocalizedString(#"ship", nil);
UITabBarController *tabBar = [[UITabBarController alloc] init];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle: nil];
//[application setStatusBarStyle:UIStatusBarStyleBlackTranslucent];
tvc = [storyboard instantiateViewControllerWithIdentifier:#"thirdview"];
fvc = [storyboard instantiateViewControllerWithIdentifier:#"firstview"];
svc = [storyboard instantiateViewControllerWithIdentifier:#"SecondViewController"];
pvc =[storyboard instantiateViewControllerWithIdentifier:#"PayViewController"];
fvc.tabBarItem.title = name1;
fvc.tabBarItem.image = [UIImage imageNamed:#"home.png"];
fvc.tabBarItem.titlePositionAdjustment = UIOffsetMake(2.0, 0);
tvc.tabBarItem.title = name2;
tvc.tabBarItem.image = [UIImage imageNamed:#"ping.png"];
tvc.tabBarItem.titlePositionAdjustment = UIOffsetMake(0, 2.0);
svc.tabBarItem.title = name3;
svc.tabBarItem.image = [UIImage imageNamed:#"zoom.png"];
svc.tabBarItem.titlePositionAdjustment = UIOffsetMake(-5.0, 0);
NSLog(#"appdelegate %# and %#",svc,svc.title);
tabBar.viewControllers = [NSArray arrayWithObjects:fvc,svc,tvc,nil];
// the below line does not allow [self.navigationController pushViewController:svNew animated:YES]; to function
self.window.rootViewController = tabBar;
// Override point for customization after application launch.
return YES;
In my fvc view im performing change view operation in okPressed method:
- (IBAction)okPressed:(id)sender {
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle: nil];
SecondViewController *svNew = [storyboard instantiateViewControllerWithIdentifier:#"SecondViewController"];
[self.navigationController pushViewController:svNew animated:YES];
}
When i comment the code in the appdelegate method the switching between the views thru the okPressed method is executed successfully. But when I uncomment the appDelegate method it does not perform switching. What i found out was , the code in appdelegate method "self.window.rootViewController = tabBar;" is the culprit. Can anyone guide me on this.

I think you should embed your UITabBarController in a Navigation Controller to make it work:
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:tabBar];
and then
self.window.rootViewController = navController;
Otherwise you can't push anything since you probably got no UINavigationController to push things to!

Related

ViewController lost reference when push notification was being clicked and when the app was in background too

App is in Background
Push notification is received and clicked
App will open and be redirect to the SecondViewController and the back button is clicked
When click to the back button from SecondViewController and back to FirstViewController the "Menu" loss the reference from MenuViewController
Push notification is received and clicked
App will open and be redirect to the SecondViewController and the back button is clicked
When click to the back button from SecondViewController and back to FirstViewController the "Menu" loss the reference from MenuViewController
My Code:
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
if (application.applicationState == UIApplicationStateActive) {
.......
} else {
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UINavigationController *navigationController=[[UINavigationController alloc] init];
self.window.rootViewController = nil;
self.window.rootViewController = navigationController;
MenuViewController *menuViewController = [storyboard instantiateViewControllerWithIdentifier:#"MenuViewController"];
[navigationController pushViewController:menuViewController animated:NO];
HomeViewController *homeViewController = [storyboard instantiateViewControllerWithIdentifier:#"HomeViewController"];
[navigationController pushViewController:homeViewController animated:NO];
AllNewsNotificationViewController *allNewsNotificationViewController = [storyboard instantiateViewControllerWithIdentifier:#"AllNewsNotificationViewController"];
[navigationController pushViewController:allNewsNotificationViewController animated:YES];
[self.window makeKeyAndVisible];
}
My MenuViewController impl:
#implementation MenuViewController
- (id)init {
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
self = [storyboard instantiateViewControllerWithIdentifier:#"MenuViewController"];
if (!self) {
return self;
}
self.navigationController = [[UINavigationController alloc] initWithRootViewController:self.homeViewController];
NSDictionary *options = #{
PKRevealControllerRecognizesPanningOnFrontViewKey : #YES,
PKRevealControllerDisablesFrontViewInteractionKey : #NO
};
self.revealController = [SubviewPKRevealViewController revealControllerWithFrontViewController:self.navigationController leftViewController:self options:options];
self.revealController.revealDelegate = self.homeViewController;
// The target view controller must implement this method
self.navBarGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self.homeViewController action:#selector(menuPan:)];
[self.navigationController.navigationBar addGestureRecognizer:self.navBarGesture];
self.view.backgroundColor = [[Configurations sharedInstance] menuBackgroundColor];
_topView.backgroundColor = [[Configurations sharedInstance] navegationbarBackgroundColor];
return self;
}
Menu shortcut (button) from MenuViewController lost the reference and doesn't works.

SWRevealViewController not able to call from the appdelegate.m

I am calling SWRevealViewController in Appdelegate.m
SWRevealViewController *svc = self.revealViewController;
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
FrontVC *homeVC = [storyboard instantiateViewControllerWithIdentifier:#"FrontVC"];
[svc setFrontViewController:homeVC animated:NO];
[svc revealToggleAnimated:YES];
But i am not able to load FrontVC controlller .
what is right way to call
For Swift 2.2
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let sw = storyboard.instantiateViewControllerWithIdentifier("SWRevealViewController") as! SWRevealViewController
self.window?.rootViewController = sw
let cv = storyboard.instantiateViewControllerWithIdentifier("IDOFCONTROLLER") as! NAMEOFCONTROLLER
let navigationController = UINavigationController(rootViewController: cv)
sw.pushFrontViewController(navigationController, animated: true)
I hope this one helps.
UIStoryboard * storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
// this any item in list you want navigate to
yourHomeViewController *home = (yourHomeViewController *) [storyboard instantiateViewControllerWithIdentifier:#"leid"];
yourSideMenuViewController *slidemenu = (yourSideMenuViewController *)[storyboard instantiateViewControllerWithIdentifier:#"MenuView"];
UINavigationController *nav = [[UINavigationController alloc]initWithRootViewController:home];
UINavigationController *smVC = [[UINavigationController alloc]initWithRootViewController:slidemenu];
// define rear and frontviewcontroller
SWRevealViewController *revealController = [[SWRevealViewController alloc]initWithRearViewController:smVC frontViewController:nav];
// make it as root
self.window.rootViewController = revealController;
We can't call RevealViewController in App Delegate.
You can directly add this in Your ViewController for Front & rear.
Have you declared and initialized revealViewController anything like this?
#interface AppDelegate ()
#property (strong, nonatomic) SWRevealViewController *revealViewController;
#end
/* ... */
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.revealViewController = /* ... init ... */;
/* ... your code here ... */
}
I didn't use a storyboard but did it like this:
SWRevealViewController *revealController = [[SWRevealViewController alloc] initWithRearViewController:menuViewController frontViewController:frontNavigationController];
SWRevealViewController *viewController = revealController;
I think u can put the start indicator in the SWRevealViewController in ur storyboard, give the login VC a name
//if user is logged in - In login VC
[[NSUserDefaults standardUserDefaults] setValue:1 forKey:isLogged];
//In Appdelegate
if([[NSUserDefaults standardUserDefaults] valueForKey:isLogged] == 1)
{
NSLog(#"have data");
//Start straight into normal SWRevealVC
self.window.rootViewController = [[UIStoryboard storyboardWithName:#"Main" bundle:[NSBundle mainBundle]] instantiateInitialViewController];
}
else
{
//If not, make your root VC the login viewcontroller
UIViewController* rootController = [[UIStoryboard storyboardWithName:#"Main" bundle:[NSBundle mainBundle]] instantiateViewControllerWithIdentifier:#"LoginViewController"];
self.window.rootViewController = rootController;
}

Launching ViewController from AppDelegate

I have a custom URL scheme and i want to open a certain ViewController which is not the root when i go to this URL. I have been able to do that and what remains is pushing this ViewController into the navigationController from the AppDelegate where i handle my URL like this :
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation {
if ([[url scheme] isEqualToString:#"njoftime"]) {
NSDictionary *getListingResponse = [[NSDictionary alloc]init];
getListingResponse = [Utils getListing:[url query]];;
if ([[getListingResponse objectForKey:#"status"] isEqualToString:#"success"]) {
ListingViewController *listingView = [[ListingViewController alloc]init];
[self.window.rootViewController.navigationController pushViewController:listingView animated:YES];
return YES;
}
but it only launches my app and not the ListingViewController i want to launch.
Any idea how can i do it differently ?
Issue
To deal with pushing and popping the viewControllers from AppDelegate, you need to use [UIApplication sharedApplication] which keeps track to all of viewControllers, beginning with root one.
Solution
To PUSH ViewController from AppDelegate
ListingViewController *listingVC = [[ListingViewController alloc] init];
[(UINavigationController *)self.window.rootViewController pushViewController:listingVC animated:YES];
To POP that ViewController you just presented, you need to use this code
[(UINavigationController *)[UIApplication sharedApplication].keyWindow.rootViewController popViewControllerAnimated:YES ];
If your using storyboard then you could use below lines for pushing your VC.
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
YOURCLASS *obj=[storyboard instantiateViewControllerWithIdentifier:#"YOUR_CLASS_STORYBOARD_ID"];
[self.window.rootViewController.navigationController pushViewController:obj animated:YES];
Update:-
ListingViewController *listingVC = [[ListingViewController alloc] init];
UINavigationController *navCon = [[UINavigationController alloc] initWithRootViewController:listingVC];
[self.window.rootViewController presentViewController:navCon animated:YES completion:nil];
Write this code in didFinishingWithLaunchingOptions
SecViewController *Vc = [[UIStoryboard storyboardWithName:#"Main" bundle:nil]instantiateViewControllerWithIdentifier:#"second"];
[(UINavigationController *)self.window.rootViewController pushViewController:Vc animated:YES];
For Swift 3 version:
let mainStoryboardIpad : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let initialViewControlleripad : UINavigationController = mainStoryboardIpad.instantiateViewController(withIdentifier: "initial") as! UINavigationController
self.window = UIWindow(frame: UIScreen.main.bounds)
self.window?.rootViewController = initialViewControlleripad
self.window?.makeKeyAndVisible()
If you want to push a UIViewController, you probably are forgetting to init it with the NibName:
LoginViewController *loginViewController = [[LoginViewController alloc]initWithNibName:#"LoginViewController" bundle:nil];
Your AppDelegate.m should look like this:
#import "TestViewController.h"
#interface AppDelegate ()
#property (strong, nonatomic) TestViewController *viewController;
#end
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.viewController = [[TestViewController alloc]init];
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
}

Login Screen and Navigation controller

So in my App.Delegate I'm doing this -
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.loginViewController = [[LoginViewController alloc] initWithNibName:#"LoginView" bundle:[NSBundle mainBundle]];
UINavigationController *navigation = [[UINavigationController alloc] initWithRootViewController: self.loginViewController];
self.window.rootViewController = navigation;
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
and in my login controller I'm doing this -
- (IBAction)login:(UIButton *)sender {
NSString *username = self.userName.text;
NSString *password = self.password.text;
[AccountUtils emailLogin:username password:password useCookie:true callback:^(NSDictionary *loginResponseJSON){
if([loginResponseJSON count] != 0){
[self performSelectorOnMainThread:#selector(displaySearchController) withObject:nil waitUntilDone:YES];
// [self performSelectorOnMainThread:#selector(switchState) withObject:nil waitUntilDone:YES];
} else {
//incorrect entry info view here.
}
}];
}
- (void) displaySearchController {
SearchViewController *searchViewController = [[SearchViewController alloc] initWithNibName:#"SearchView" bundle:[NSBundle mainBundle]];
UINavigationController *navigator = self.navigationController;
[navigator popViewControllerAnimated: YES];
[navigator pushViewController: searchViewController animated:YES];
}
If I correctly login, I go to the second controller's view, but at the top I'm still allowed to go 'back' to the login page. I don't want that to happen and I thought this case would be taken care off by the popViewControllerAnimated line. How do I make it so that when I login, I am not allowed to go back to the login page?(in other words, I guess pop the login controller off the navigation controller's stack?)
If you want just to remove the loginVC you could set the new navigationController as the rootViewController of the AppDelegate after the user has logged in. So you could move the displaySearchController method in the AppDelegate and call this method (from the loginVC) after the user has logged in:
-(void)displaySearchController{
SearchViewController *searchViewController = [[SearchViewController alloc] initWithNibName:#"SearchView" bundle:[NSBundle mainBundle]];
UINavigationController *navigation = [[UINavigationController alloc] initWithRootViewController: searchViewController];
self.window.rootViewController=navigation;
}
Otherwise, if you really want the push animation, you can remove the loginVC from the navigationController viewControllers stack in the viewDidAppear of SearchDispalyController:
-(void)viewDidAppear:(BOOL)animated{
NSMutableArray *stackVCs=[self.navigationController.viewControllers mutableCopy];
int idx=[stackVCs indexOfObject:self];
//this remove the previous viewcontroller from the stack
[stackVCs removeObjectAtIndex:idx-1];
self.navigationController.viewControllers=stackVCs;
[super viewDidAppear:animated];
}
Also in the loginVC just before push the searchVC you should call this to hide the back button:
[navigation.navigationItem setHidesBackButton:YES];
You don't want to use a UINavigationController with the LoginViewController and you don't want to push the SearchViewController. Instead, use a UINavigationController with SearchViewController and when you display it, make it the rootViewController.
Do this to achieve what you want.
Move the displaySearchController method to your AppDelegate.m file
Do declare the displaySearchController method in AppDelegate.h file
Now Define the displaySearchController method in AppDelegate.m file as :
- (void) displaySearchController {
SearchViewController *searchViewController = [[SearchViewController alloc] initWithNibName:#"SearchView" bundle:[NSBundle mainBundle]];
UINavigationController *navigator = [[UINavigationController alloc]initWithRootViewController:searchViewController];
self.window.rootViewController = navigator;
}
Call a new local method showNewViewController from your loginController as :
[self performSelectorOnMainThread:#selector(showNewViewController) withObject:nil waitUntilDone:YES];
Now define showNewViewController in your loginController.m file as
-(void)showNewViewController {
AppDelegate *appDele = [UIApplication sharedApplication].delegate;
[appDele displaySearchController];
}
Don't forget to import the AppDelegate.h file to your loginController.m
This will certainly help you.

PushView on PresentViewController iOS

I want to Push my viewController on PresentViewController
When i click on button initially i am loading PresentViewController, here is my code.
- (IBAction)JoinClicked:(id)sender{
JoinWithViewController *detail_view_controller = [[JoinWithViewController alloc] initWithNibName:#"JoinWithViewController" bundle:nil];
[self.view.window.rootViewController presentViewController:detail_view_controller
animated:YES
completion:NULL];
}
this works fine, but when i click on button which is there on PresentViewController on click i want to Push my view, but in does not pushes.
Please help, Thanks in advance.
JoinWithViewController *detail_view_controller = [[JoinWithViewController alloc] initWithNibName:#"JoinWithViewController" bundle:nil];
[self.navigationController pushViewController:detail_view_controller animated:YES];
Try like this to push viewController. If you use TabBar do like this in AppDelegate. If you create TabBar Drag and drop means leave that. Create TabBar Programatically like below.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
UITabBarController *tabController = [[UITabBarController alloc]init];
self.viewController = [[CalculatorViewController alloc] initWithNibName:#"CalculatorViewController" bundle:nil];
UITabBarItem *tab_item1 = [[UITabBarItem alloc]init];
//tab_item1.title = #"Calculator";
tab_item1.image = [UIImage imageNamed:#"Calculator.png"];
[self.viewController setTabBarItem:tab_item1];
UINavigationController *nav1 = [[UINavigationController alloc]initWithRootViewController:self.viewController];
ShowPhoneViewController *phone = [[ShowPhoneViewController alloc]init];
UITabBarItem *tab_item2 = [[UITabBarItem alloc]init];
tab_item2.title = #"Latest Mobiles";
tab_item2.image = [UIImage imageNamed:#"Mobile.png"];
[phone setTabBarItem:tab_item2];
UINavigationController *nav2 = [[UINavigationController alloc]initWithRootViewController:phone];
CurrencyConvertorViewController *currency = [[CurrencyConvertorViewController alloc]init];
UITabBarItem *tab_item3 = [[UITabBarItem alloc]init];
tab_item3.title = #"Units Convertor";
tab_item3.image = [UIImage imageNamed:#"Dollar.png"];
[currency setTabBarItem:tab_item3];
UINavigationController *nav3 = [[UINavigationController alloc]initWithRootViewController:currency];
SettingsPageViewController *setting = [[SettingsPageViewController alloc]init];
UITabBarItem *tab_item4 = [[UITabBarItem alloc]init];
tab_item4.title = #"Settings";
tab_item4.image = [UIImage imageNamed:#"Settings.png"];
[setting setTabBarItem:tab_item4];
UINavigationController *nav4 = [[UINavigationController alloc]initWithRootViewController:setting];
tabController.viewControllers = [NSArray arrayWithObjects:nav1, nav2, nav3, nav4, nil];
self.window.rootViewController = tabController;
[self.window makeKeyAndVisible];
return YES;
}
I hope you got now
pushviewcontroller is the feature of UINavigationController where you can push one viewcontroller on another vierw controller. Here you are using a single viewcontroller as a rootviewcontroller so either you must change your rootviewcontroller to UINavigationcontroller or you can use "addSubview method" to add new viewController on the current viewcontroller.
but the better option is to add uinavigationcontroller as a rootviewcontroller.
AppDelegate.m
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
FirstViewController *first = [[FirstViewController alloc]
initWithNibName:#"FirstViewController" bundle:nil];
UINavigationController *navController =[[UINavigationController alloc]
initWithRootViewController:first];
[self.window setRootViewController:navController];
}
Now when as you want to switch from FirstViewController to SecondViewController on button clicked than you have to use pushviewcontroller
FirstViewController.h
-(void) nextBtnPressed {
SecondViewController *second = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
[self.navigationController pushViewController:second animated:TRUE];
}

Resources