how to embed navigation controller in a view programmatically? - ios

I have a view controller which is my HomeViewController, and I have a modal segue between them.
This is the HomeViewController:
import "HomePageViewController.h"
#import "CreatePageViewController.h"
#import "StackTableViewController.h"
#import "PopUpView.h"
#interface HomePageViewController ()
#property (nonatomic, strong) IBOutlet UIButton *toggleButton;
#property (nonatomic, strong) CreatePageViewController *modalTest;
#property (nonatomic, strong) PopUpView *popup;
#end
#implementation HomePageViewController
-(UIStatusBarStyle)preferredStatusBarStyle{
return UIStatusBarStyleLightContent;
}
-(void)viewDidLoad {
[super viewDidLoad];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:Nil];
_modalTest = [storyboard instantiateViewControllerWithIdentifier:#"ModalTest"];
[_toggleButton addTarget:self action:#selector(go) forControlEvents:UIControlEventTouchUpInside];
[[NSNotificationCenter defaultCenter]addObserver:self selector:#selector(hide) name:#"HideAFPopup" object:nil];
}
-(void)go {
_popup = [PopUpView popupWithView:_modalTest.view];
[_popup show];
}
-(void)hide {
[_popup hide];
}
- (IBAction)pushToNextViewController:(id)sender {
StackTableViewController *vc = [[StackTableViewController alloc]init];
[self presentModalViewController:vc animated:YES];
}
-(void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
#end
I want to add a navigation controller to StackTableViewController...its just a table view and I want it to have a navigation controller, how should I do this?
Also, why xcode tells me my modal method presentModalViewController is deprecated?
tnx

Create a new instance of UINavigationController, with your StackTableViewController as its rootViewController. Then present the navigation controller:
- (IBAction)pushToNextViewController:(id)sender {
StackTableViewController *vc = [[StackTableViewController alloc]init];
UINavigationController *navCtrl = [[UINavigationController alloc] initWithRootViewController:vc];
[self presentViewController:navCtrl animated:YES completion:nil];
}
Note that presentModalViewController:animated: is deprecated because it has been replaced by presentViewController:animated:completion:.

Related

UINavigationController not appearing?

I have a Add View where when you tap on Category, the following code is executed
- (void)categoryTapped {
CategoryGroupViewController *categoryGroupViewController = [[CategoryGroupViewController alloc] initWithNibName:#"CategoryGroupViewController" bundle:nil];
[self presentViewController:categoryGroupViewController animated:YES completion:nil];
}
CategoryGroupViewController.h looks like
#interface CategoryGroupViewController : UIViewController<UITableViewDataSource, UITableViewDelegate>
#property (nonatomic, strong) UINavigationController *navigationController;
#property (strong, nonatomic) IBOutlet UITableView *tableView;
#end
CategoryGroupViewController.m looks like
#import "CategoryGroupViewController.h"
#import "Helper.h"
static NSString *CellIdentifier = #"Cell";
#interface CategoryGroupViewController ()
#property(nonatomic, strong) NSArray *categories;
#end
#implementation CategoryGroupViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// (todo) should come from API
self.categories = #[#"Food & Drink", #"Utilities"];
}
[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:CellIdentifier];
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
NSLog(#"categoryGroup View loaded");
self.navigationController = [[UINavigationController alloc] initWithRootViewController:self];
self.navigationController.title = #"Pick Category";
}
...
}
When I run my application, I see the following in log
2014-11-20 21:29:53.589 myapp-ios[30332:70b] categoryGroup View loaded
But on Simulator, I see
Why don't I see NavigationController?
As you are presenting your CategoryGroupViewController it will not show Navigation Bar by default.
You have to set your CategoryGroupViewController as rootViewController for UINavigationController and instead of presenting CategoryGroupViewController present newly created UINavigationController.
- (void)categoryTapped{
CategoryGroupViewController *categoryGroupVC = [[CategoryGroupViewController alloc] initWithNibName:#"CategoryGroupViewController" bundle:nil];
UINavigationController *navController = [[UINavigationController alloc]initWithRootViewController: categoryGroupVC];
[self presentViewController:categoryGroupViewController animated:YES completion:nil];
}
as i mentioned above if u want a navigaioncontroller u can set CategoryGroupViewController as a root view for a navigation controller and present it for example,
- (void)categoryTapped
{
CategoryGroupViewController *categoryGroupViewController = [[CategoryGroupViewController alloc] initWithNibName:#"CategoryGroupViewController" bundle:nil];
//add this
UINavigationController *navController = [[UINavigationController alloc]initWithRootViewController: categoryGroupViewController];
//present the navigation controller which contains root view controller categoryGroupViewController
[self presentViewController:navController animated:YES completion:nil];
}
You need to instantiate a rootViewController before View did load
[alink]https://developer.apple.com/library/ios/featuredarticles/ViewControllerPGforiPhoneOS/ViewLoadingandUnloading/ViewLoadingandUnloading.html
UIViewController already as a navigationController property, so this is redundant:
// Remove this property from CategoryGroupViewController
#property (nonatomic, strong) UINavigationController *navigationController;
Structuring the user interface in the way you are attempting is also incorrect, and would result in a circular reference between CategoryGroupViewController and UINavigationController. First you need to modify your -viewDidLoad method like so:
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
NSLog(#"categoryGroup View loaded");
// UINavigationController will use this automatically.
self.title = #"Pick Category";
}
Then you should change the way you go about preseting the view controller in your original method:
- (void)categoryTapped {
CategoryGroupViewController *categoryGroupViewController = [[CategoryGroupViewController alloc] initWithNibName:#"CategoryGroupViewController" bundle:nil];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:categoryGroupViewController];
[self presentViewController:navController animated:YES completion:nil];
}
Finally, the introduction in the UINavigationController documentation has a great explanation of how the class should be used. Taking a few minutes to read it would help you tremendously in the future.

Change the starting View in a tabbed iOS application

i have created a tabbed application and created another file, called LogInScreen,
I want to change the usual view which comes up at the application launch to this new LogInFile, but everything I tried didn't work.
This is the AppDelegate.h file:
#import <UIKit/UIKit.h>
#import "LogInScreen.h"
#interface LogInScreen : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) LogInScreen *logInView;
#end
#interface AppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) UIWindow *window;
#end
At the first #implementation appears an error message: Duplicate interface definition for class 'LogInScreen', I guess because of the LogInScreen.h file. I don't know how to get it to work properly.
And this the start of the AppDelegate.m:
#import "AppDelegate.h"
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions: (NSDictionary *)launchOptions
{
[self.logInView addSubview:_logInView.view];
[self.logInView makeKeyAndVisible];
[self.logInView setRootViewController:_logInView];
// Override point for customization after application launch.
return YES;
}
I found this code on this website, but it didn't work...
Here's the LogInScreen.h file:
#import <UIKit/UIKit.h>
#interface LogInScreen : UIViewController{
NSString *password;
IBOutlet UITextField *passwordField;
}
- (IBAction)enterPassword;
- (IBAction)savepassword:(id)sender;
- (IBAction)returnKey:(id)sender;
- (IBAction)switchView:(id)sender;
#end
and the LogInScreen.m:
#import "LogInScreen.h"
#import "FirstViewController.h"
/* #import "AppDelegate.h"
int main(int argc, char * argv[])
{
#autoreleasepool {
return UIApplicationMain()(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
*/
#interface LogInScreen ()
#end
#implementation LogInScreen
- (IBAction)enterPassword
{
NSString *passwordString = [NSString stringWithFormat:#"12345"];
if ([passwordField.text isEqualToString:passwordString]) {
/*[self switchView:nil]; */
}
else {
UIAlertView *incorrectPassword = [[UIAlertView alloc] initWithTitle:#"Falsches Passwort" message:#"Dieses Passwort ist falsch! Geben Sie bitte das korrekte Passwort ein!" delegate:self cancelButtonTitle:#"Zurück" otherButtonTitles:nil, nil];
[incorrectPassword show];
}
}
- (IBAction)savepassword:(id)sender {
password = [[NSString alloc] initWithFormat:passwordField.text];
[passwordField setText:password];
NSUserDefaults *stringDefault = [NSUserDefaults standardUserDefaults];
[stringDefault setObject:password forKey:#"stringKey"];
}
- (IBAction)returnKey:(id)sender {
[sender resignFirstResponder];
}
- (IBAction)switchView:(id)sender {
FirstViewController *main = [[FirstViewController alloc] initWithNibName:nil bundle:nil];
[self presentViewController:main animated:YES completion:NULL];
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[passwordField setText:[[NSUserDefaults standardUserDefaults] objectForKey:#"stringKey"]];
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
Would be cool if someone could help me
Following my comment, you can use this code to show a modal login view before your main tabbed view:
// Main menu view controller
MainViewController *mainViewController = [[MainViewController alloc] initWithNibName:#"MainViewController" bundle:nil];
UINavigationController *mainNavigationController = [[UINavigationController alloc] initWithRootViewController:mainViewController];
self.tabBarController = [[UITabBarController alloc] init];
self.tabBarController.delegate = self;
self.tabBarController.viewControllers = [NSArray arrayWithObjects:mainNavigationController, nil];
self.window.rootViewController = self.tabBarController;
[self.window.rootViewController.view setOpaque:NO];
self.window.rootViewController.view.backgroundColor = [UIColor clearColor];
self.tabBarController.selectedIndex = 0;
[self.window setRootViewController:self.tabBarController];
[self.window makeKeyAndVisible];
// Login modal view controller
LoginViewController *loginController = [[LoginViewController alloc] initWithNibName:#"LoginViewController" bundle:nil];
[self.tabBarController presentViewController:loginController animated:NO completion:nil];
Place your login screen as intial view in MainStoryBoard .Drag a drop a uitabbarcontroller connect a segue from loginscreen to uitabbar and present modal that tabbar from a button in the login screen .

add a button to all pushed viewControllers' navigation bar which performs an action from main navigation controller

NavigationController.h
#import <UIKit/UIKit.h>
#protocol NavigationControllerDelegate;
#interface NavigationController : UINavigationController<UINavigationControllerDelegate>
#property (nonatomic , assign)id<NavigationControllerDelegate , UINavigationControllerDelegate> delegate;
-(void)cancelImagePicker:(id)sender;
#end
#protocol NavigationControllerDelegate <NSObject>
- (void)mediaPickerController:(NavigationController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info;
- (void)mediaPickerControllerDidCancel:(NavigationController *)picker;
#end
NavigationController.m
#import "NavigationController.h"
#import "DataViewController.h"
#interface NavigationController ()
#end
#implementation NavigationController
#synthesize delegate;
-(id)init{
UIViewController *controller = [[DataViewController alloc]initWithNibName:#"DataViewController" bundle:nil];
self = [super initWithRootViewController:controller];
if (self) {
self.navigationBar.topItem.title = #"Data Table";
self.navigationBar.tintColor = [UIColor clearColor];
UIBarButtonItem *rightButton = [[UIBarButtonItem alloc] initWithTitle:#"Cancel"
style:UIBarButtonSystemItemCancel target:self action:#selector(cancelImagePicker:)];
self.navigationBar.topItem.rightBarButtonItem = rightButton;
}
return self;
}
-(void)cancelImagePicker:(id)sender{
[delegate mediaPickerControllerDidCancel:self];
}
#end
DataViewController.m
.....
-(void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath{
secondViewController *secondController = [[secondViewController alloc]initWithNibName:#"secondViewController" bundle:nil ];
[self.navigationController pushViewController: secondController animated:YES];
}
.......
I want to add a "cancel" button on secondViewController's navigation bar which performs the action -(void)cancelImagePicker:(id)sender; from NavigationController.m. And the same for pushed third, fourth and fifthViewController. How can this be achieved? Do i have to write code in each viewController or Can i write in common?
I have presented the NavigationController from MainViewController on buttonClick as
- (IBAction)navView:(id)sender {
NavigationController * controller = [[NavigationController alloc]init];
controller.delegate = self;
[self presentViewController:controller animated:YES completion:nil];
}
and implemented the delegation methods there.
You can use notification center instead of delegates, the idea is,
[NSNotificationCenter DefaultCenter] addObserver]

iPad application with multiple DetailView and have navigation in detailview

i search for a way to have multiple detail view in iPad application and i find the sample code in apple developer site http://developer.apple.com/library/ios/#samplecode/MultipleDetailViews/Introduction/Intro.html , but now i want to have navigation in detail view which this sample does not cover, i add uinavigationcontroller to detail view as :
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
ReportsViewController_iPad *master = [[ReportsViewController_iPad alloc] initWithNibName:#"ReportsViewController_iPad" bundle:nil];
DetailViewController_iPad *detail = [[DetailViewController_iPad alloc] initWithNibName:#"DetailViewController_iPad" bundle:nil];
UINavigationController *masterNavController = [[[UINavigationController alloc] initWithRootViewController:master ] autorelease];
UINavigationController *detailNavController = [[[UINavigationController alloc] initWithRootViewController:detail ] autorelease];
splitViewController.viewControllers = [NSArray arrayWithObjects:masterNavController , detailNavController, nil];
[window addSubview:splitViewController.view];
[window makeKeyAndVisible];
return YES;
}
but when i run the sample i got error
[UINavigationController showRootPopoverButtonItem:]: unrecognized selector sent to instance...
showRootPopoverButtonItem is a method define in a protocol in RootViewController
#protocol SubstitutableDetailViewController
- (void)showRootPopoverButtonItem:(UIBarButtonItem *)barButtonItem;
- (void)invalidateRootPopoverButtonItem:(UIBarButtonItem *)barButtonItem;
#end
---- ReportsViewController.h
#protocol SubstitutableDetailViewController
- (void)showRootPopoverButtonItem:(UIBarButtonItem *)barButtonItem;
- (void)invalidateRootPopoverButtonItem:(UIBarButtonItem *)barButtonItem;
#end
#protocol DetailViewControllerManagerDelegate
-(void) didSelectRowAtIndexPathPopOver:(NSString *)ID;
#end
#interface ReportsViewController_iPad : ReportsViewController<UISplitViewControllerDelegate , DetailViewControllerManagerDelegate>
{
UISplitViewController *splitViewController;
UIPopoverController *popoverController;
UIBarButtonItem *rootPopoverButtonItem;
}
#property (nonatomic, assign) IBOutlet UISplitViewController *splitViewController;
#property (nonatomic, retain) UIPopoverController *popoverController;
#property (nonatomic, retain) UIBarButtonItem *rootPopoverButtonItem;
#property(nonatomic, retain) id<DetailViewControllerManagerDelegate> delegate;
-(void)didSelectRowAtIndexPath:(NSString*)ID;
#end
--DetailViewController.h
#import <UIKit/UIKit.h>
#import "ReportsViewController_iPad.h"
#interface DetailViewController_iPad : UIViewController<SubstitutableDetailViewController>
{
UIToolbar *toolbar;
}
#property (nonatomic, retain) IBOutlet UIToolbar *toolbar;
#end
--DetailViewController.m
#import "DetailViewController_iPad.h"
#implementation DetailViewController_iPad
#synthesize toolbar;
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)viewDidUnload
{
[super viewDidUnload];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
#pragma mark -
#pragma mark Managing the popover
- (void)showRootPopoverButtonItem:(UIBarButtonItem *)barButtonItem {
// Add the popover button to the toolbar.
NSMutableArray *itemsArray = [toolbar.items mutableCopy];
[itemsArray insertObject:barButtonItem atIndex:0];
[toolbar setItems:itemsArray animated:NO];
[itemsArray release];
}
- (void)invalidateRootPopoverButtonItem:(UIBarButtonItem *)barButtonItem {
// Remove the popover button from the toolbar.
NSMutableArray *itemsArray = [toolbar.items mutableCopy];
[itemsArray removeObject:barButtonItem];
[toolbar setItems:itemsArray animated:NO];
[itemsArray release];
}
- (void)dealloc {
[toolbar release];
[super dealloc];
}
#end
So Thanks in advance.
Where definition of method showRootPopoverButtonItem is present, seems like this is not defined. You need to define it.
If you want to avoid crash then you can use -
if ([aViewController respondsToSelector:#selector(showRootPopoverButtonItem:)]) {
[aViewController performSelector:#selector(showRootPopoverButtonItem:) withObject:self.rootPopoverButtonItem];
}
EDIT -
I have checked this and found what you are doing wrong , for e.g. code in willHideViewController-
UIViewController <SubstitutableDetailViewController> *detailViewController = [splitViewController.viewControllers objectAtIndex:1];
this is expecting a view controller, while you are passing navigation controller which in turn has view controller(similar at some other position), so you need to alter these codes as well if you want to pass navigation controller from app delegate.

Call a method in the super from a child popupviewcontroller

I need to call a method in the viewcontroller that creates a popupviewcontroller, from the created popupviewcontroller.
For iPad I create it like this:
if (!self.flipsidePopoverController) {
FlipsideViewController *controller = [[[FlipsideViewController alloc] initWithNibName:#"FlipsideViewController" bundle:nil] autorelease];
controller.delegate = self;
self.flipsidePopoverController = [[[UIPopoverController alloc] initWithContentViewController:controller] autorelease];
}
if ([self.flipsidePopoverController isPopoverVisible]) {
[self.flipsidePopoverController dismissPopoverAnimated:YES];
}
else
{
/// The important part ///
[self.flipsidePopoverController presentPopoverFromRect:CGRectMake((self.view.frame.size.width-320), 0, (self.view.frame.size.width), 10) inView:self.view permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
}
Now I wish to call a method in my main view controller from within the popup. How can I achieve that?
My iPhone equivalent is this:
// Creating it //
FlipsideViewController *controller = [[[FlipsideViewController alloc] initWithNibName:#"FlipsideViewController" bundle:nil] autorelease];
controller.delegate = self;
controller.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:controller animated:YES];
Calling a method from within the popup:
if ([self.presentingViewController isKindOfClass:[MainViewController class]])
[(MainViewController*)self.presentingViewController resetClock];
Give the displayed view controller a reference to your main view controller. Eg:
#class MainViewController;
#interface FlipsideViewController : UIViewController
{
}
#property (nonatomic, assign) MainViewController *mainController;
#end
(Don't forget the #synthesize in the implementation!)
Later when you present the popover, just set the property:
[controller setMainController:self];
.h
#import <UIKit/UIKit>
#import AppDelegate.h"
#interface FlipsideViewController : UIViewController
{
}
#property (nonatomic, assign) MainViewController *mainController;
#end
.m
#import "FlipsideViewController.h"
#import "MainViewController.h"
#interface FlipsideViewController ()
#end
#implementation FlipsideViewController
#synthesize mainController = _mainController;
// methods
#end

Resources