I am new working with Objective C, I have good knowledge with storyboards but now I try to change the root view controller of a UINavigationController by code, it happens that it depends on a variable, I will set the root, but I don't know how to configure this action besides what I have my custom class for my UINavigationControllers. I hope you can help me.Keep in mind that this view is the 3rd screen in the app.
#interface PCCatalogNavigationController () <UINavigationControllerDelegate>
#end
#implementation PCCatalogNavigationController
- (void)viewDidLoad{
if (status == 1){
//TableViewViewController
} else {
//Optional StarViewController
}
}
#end
inside Your App delegate just add Property of you Navigation Controller
#property (nonatomic , strong) UINavigationController *navigationController;
and Inside
-(BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
TableViewViewController *TableViewView = [[UIStoryboard
storyboardWithName:#"Main" bundle:nil]
instantiateViewControllerWithIdentifier:#"TableViewViewController"];
StarViewController *StarView = [[UIStoryboard
storyboardWithName:#"Main" bundle:nil]
instantiateViewControllerWithIdentifier:#"StarViewController"];
if (status == 1){
self.navigationController =
[[UINavigationController alloc]
initWithRootViewController:TableViewView];
} else {
//Optional
StarViewController self.navigationController =
[[UINavigationController alloc]
initWithRootViewController:StarView];
}
}
instead UINavigationController you can use you customNavigationcontroller
Related
I had Implemented MFSideMenu in my Application to display left side slide in-out menu.Now I would like to recognise swipe in and swipe out (i.e. Sidemenu open or closed status)by creating delegate method in ThirdParty class MFSideMenuContainerViewController.h as
#import <UIKit/UIKit.h>
#import "MFSideMenuShadow.h"
#class MFSideMenuContainerViewController;
#protocol MFSideMenuContainerViewControllerViewDelegate <NSObject> //define delegate protocol
- (void)swipedLeftSidemenu:(BOOL)isOpen; //define delegate method to be implemented within another class
#end //end protocol
#interface MFSideMenuContainerViewController : UIViewController<UIGestureRecognizerDelegate>
//custom delegate property
#property (nonatomic, weak) id <MFSideMenuContainerViewControllerViewDelegate> delegate1;
#end
and then call delegate method from below method of MFSideMenuContainerViewController.m
- (void)openLeftSideMenuCompletion:(void (^)(void))completion
{
if(!self.leftMenuViewController) return;
//call as below
[self.delegate1 swipedLeftSidemenu:YES];
//below is default thirdparty implementation
[self.menuContainerView bringSubviewToFront:[self.leftMenuViewController view]];
[self setCenterViewControllerOffset:self.leftMenuWidth animated:YES completion:completion];
}
Delegate method used in another viewcontroller class to detect side menu is open or closed for that I had implemented below code
in DemoViewController.h file
#import "MFSideMenuContainerViewController.h"
#interface DemoViewController : UIViewController <ContactViewDelegate,MFSideMenuContainerViewControllerViewDelegate>
in DemoViewController.m file
- (void)viewDidLoad
{
[super viewDidLoad];
MFSideMenuContainerViewController *vc2 = [[MFSideMenuContainerViewController alloc] init];
vc2.delegate1 = self;
}
//DelegateMethod Implementation
-(void)swipedLeftSidemenu:(BOOL)isOpen
{
if(isOpen)
{
// code is here if side menu is open by swiping right
}
else
{
// code is here if side menu is closed by swiping left
}
}
Now I having issue is above method in DemoViewController.m file is never called although sidemenu can be swiped left or right.Can any one guide how I can detect side menu is open or close from DemoViewController class? Or Why this method is never called ?
My appdelegate.m files having below code only
#interface AppDelegate ()
#end
#implementation AppDelegate
- (DemoViewController *)demoController
{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
DemoViewController *demoController = [storyboard instantiateViewControllerWithIdentifier:#"DemoViewController"];
return demoController;
}
- (UINavigationController *)navigationController
{
return [[UINavigationController alloc]
initWithRootViewController:[self demoController]];
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
SideMenuViewController *leftMenuViewController = [storyboard instantiateViewControllerWithIdentifier:#"SideMenuViewController"];
MFSideMenuContainerViewController *container = [MFSideMenuContainerViewController
containerWithCenterViewController:[self navigationController]
leftMenuViewController:leftMenuViewController
rightMenuViewController:nil];
self.window.rootViewController = container;
[self.window makeKeyAndVisible];
return YES;
}
Update your code In your AppDelegate.h file
#property (strong, nonatomic) UIWindow *window;
#property(strong,nonatomic)ViewController *viewController;
#property(strong,nonatomic)LeftSideViewController *leftSideViewController;
#property(strong,nonatomic)MFSideMenuContainerViewController *container;
#property(strong,nonatomic)UINavigationController *navigationController;
#end
and in your AppDelegate.m file update your code
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.container = [MFSideMenuContainerViewController containerWithCenterViewController:self.navigationController leftMenuViewController:_leftSideViewController rightMenuViewController:nil];
self.window setRootViewController:_container];
[self.window makeKeyAndVisible];
return YES;
}
Instead of delegate method I had replaced it with NotoficationCenter Observer method and that code is as below :
STEP-1
in ThirdParty class MFSideMenuContainerViewController.m as
- (void)openLeftSideMenuCompletion:(void (^)(void))completion
{
if(!self.leftMenuViewController) return;
NSDictionary* userInfo = #{#"isOpen": #"1"};
[[NSNotificationCenter defaultCenter] postNotificationName:#"swipeClassDelegateMethod" object:nil userInfo:userInfo];
//below is default thirdparty implementation
[self.menuContainerView bringSubviewToFront:[self.leftMenuViewController view]];
[self setCenterViewControllerOffset:self.leftMenuWidth animated:YES completion:completion];
}
STEP-2 : then I called below code from my DemoViewController.m file viewDidLoad method
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(swipeClassDelegateMethod:)name:#"swipeClassDelegateMethod" object:nil];
STEP-3 : Finally I implemented this function with necessary code as below in same DemoViewController.m class
-(void)swipeClassDelegateMethod:(NSNotification*)notification
{
}
I want to change view by clicking button with NavigationController
So I added a button to Main.storyboard and write some codes like
#property (weak, nonatomic) IBOutlet UIButton *button;
in my ViewController.m (Created automatically when I made my project)
And I added method
- (IBAction)buttonClicked:(id)sender {
SecondViewController *secondViewController = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
[self.navigationController pushViewController:secondViewController animated:YES];
}
(I made SecondViewController.m, SecondViewController.h, SecondViewController.xib)
After this, I started the application and clicked the button but the screen didn't change.
Actually, when I added log like
NSLog(#"%#", self.navigationController);
null was printed.
I think I need to add some code about NavigationController to AppDelegate.m but I don't know what to do. Please help me.
Try This,
in Appdelegate.m
`- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.viewController = [[ViewController alloc] initWithNibName:#"ViewController"
bundle:nil];
UINavigationController *navigation = [[UINavigationController alloc]initWithRootViewController:self.viewController];
self.window.rootViewController = navigation;
[self.window makeKeyAndVisible];
return YES;
}`
You need to embed Navigation Controller through code or Storyboard.
First select your initial viewcontroller in storyboard and embed it in NavigationController.
Then give a storyboard identifier to the second viewcontroller.
Then lastly instantiate Second ViewController from storyboard and push it.
- (IBAction)buttonClicked:(id)sender {
SecondViewController *secondViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"SecondViewController"];
[self.navigationController pushViewController:entryController animated:YES];
}
I'm creating an application that has 2 main view controllers at the moment. The app loads into the initial viewController, and clicking a button inside should bring up the second viewController. Here's what I have:
AppDelegate.h
#import <UIKit/UIKit.h>
#import "ViewController1.h"
#interface AppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) UIWindow *window;
#property (strong, nonatomic) ViewController1 *mainViewCtr;
#property (strong, nonatomic) UINavigationController *navigationController;
#end
AppDelegate.m
- (void)applicationDidFinishLaunching:(UIApplication *)application {
_mainViewCtr = [[ViewController1 alloc] initWithNibName:#"mainViewCtr" bundle:nil];
_navigationController = [[UINavigationController alloc] initWithRootViewController:_mainViewCtr];
_window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
_window.rootViewController = _navigationController;
_navigationController.delegate = self;
_navigationController.navigationBarHidden = YES;
[_window addSubview:_navigationController.view];
[self.window makeKeyAndVisible];
}
and my button method inside viewcontroller1:
- (IBAction)SessionNickNameSubmit:(id)sender {
ViewController2 *secondViewCtrl = [[ViewController2 alloc] initWithNibName:#"secondViewCtrl" bundle:nil];
[self.navigationController pushViewController:secondViewCtrl animated:YES];
}
but when I click the button the view doesn't change. I tried debugging and the code is hit, but nothing happens.
am I missing a setting somewhere?
UPDATE
I've updated all viewController variable names:
instead of ViewController1/2 I'm using mainViewCtrl and secondViewCtrl
but still no use :(
You made a typo:
it's
_window.rootViewController = _navigationController;
not
_window.rootViewController = _joinViewController;
And NeverHopeless's suggestion is also spot on. It's probably the typo AND the fact that you add your second viewcontroller as ViewController2 and not using a proper variable name.
Another suggestion is making a storyboard (if you are not using one) and adding a segue for the transition. Simply assign the segue processing to the button. Like this:
-(IBAction)SessionNicknameSubmit:(id)sender
{
[self performSegueWithIdentifier:#"identifier" sender:self ];
}
Here is a nice description of how it works and how to use it plus some useful pointers!
Obj-C is a case sensitive language, class name and instance name should not be the same like ViewController2. Try like this:
- (IBAction)SessionNickNameSubmit:(id)sender {
ViewController2 *viewController2 = [[ViewController2 alloc] initWithNibName:#"ViewController2" bundle:nil];
[self.navigationController pushViewController:viewController2 animated:YES];
}
The reason is that you have set the window's rootViewController to ViewController1.
You need to set you navigation controller to the window's rootViewController.
So that when you try to access the self.navigationController on the press of the button, it will access the navigation controller in which the self resides i.e. your window's rootViewController now.
Then it will push the next view controller properly.
After looking at almost every tutorial and every stack overflow answer, I finally found a solution that worked. I had to make an instance of the storyboard in the app delegate and use that to create my first view controller instance.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
self.joinViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"ViewController1"];
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:joinViewController];
_window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
navigationController.navigationBarHidden = YES;
_window.rootViewController = navigationController;
[_window addSubview:navigationController.view];
[self.window makeKeyAndVisible];
return YES;
}
I think the problem was that when I was creating an instance of ViewController, it was creating a new instance and binding the navigation controller to it (independent of the view controller that was showing up in the simulator). So when I was using the push method it wasn't recognizing self.NavigationController (that's why NSLog(self.NavigationController == nil) was logging 1
I'm trying to implement my own custom UIWindow class. It's named SNWindow. I read that you have to implement your own getter method, and that's what I did but it never get's past "Point 1". It's infinitely logging "Point 1", showing a black screen on the iPhone.
AppDelegate.h
#import <UIKit/UIKit.h>
#import "SNWindow.h"
#interface AppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) SNWindow *window;
- (SNWindow *)window;
#end
AppDelegate.m
...
- (SNWindow *)window
{
NSLog(#"Point 1");
//
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
//
UIViewController *viewController = [storyboard instantiateInitialViewController];
//
_window = [[SNWindow alloc] init];
_window.rootViewController = viewController;
NSLog(#"Point 2");
return _window;
}
Any ideas on how to fix it?
Do not type the window property as SNWindow; type it as UIWindow, the normal way. Your code, in your App Delegate class, then needs to look like this:
- (UIWindow*) window {
UIWindow* w = self->_window;
if (!w) {
w = [[SNWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self->_window = w;
}
return w;
}
The rest of the App Delegate, such as application:didFinishLaunching..., should just go ahead and do what it would normally do (which might be no more than return YES).
I am creating a class object from my UIViewController and trying to push a controller from it, and it won't work.
I have been doing research but found nothing, any idea?
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.newClass = [[MyNewClass alloc] init];
self.newClass.view = self.view;
self.newClass.navigationController = self.navigationController;
[self.newClass connect];
}
...
#end
MyNewClass.h
#interface MyNewClass : NSObject<UINavigationControllerDelegate>
#property(nonatomic, retain) UIView *view;
#property(nonatomic, retain) UINavigationController *navigationController;
-(void) connect;
#end
MyNewClass.m
-(void)connect
{
OtherViewController * otherVC =
[[OtherViewController alloc] init];
self.navigationController pushViewController:otherVC animated:YES];
}
...
add folloeing code into appdelegate's didFinishLaunchingWithOptions method.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[self copyDatabaseIfNeeded];
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.viewController = [[ViewController alloc] initWithNibName:#"ViewController" bundle:nil];
self.window.rootViewController = [[UINavigationController alloc] initWithRootViewController:self.viewController];
[self.window makeKeyAndVisible];
return YES;
}
and then remove all other UINavigationController declaration and allocation. Like MyNewClass's NavigationVontroller. Because here you declare and allocate navigationcontroller in appdelegate so you can use it in whole app.
When viewDidLoad is called, the view has just been loaded but the view controller hasn't necessarily been added to a navigation controller yet. So using viewDidLoad as your trigger is not useful.
A better approach is to explicitly pass the navigation controller to the view controller when it's created. Or to implement didMoveToParentViewController: and do your configuration there.
You are pushing a viewController from a controller, which is not a part of navigationController, so first make it part of navigationController, then try