Cocoa - Adding a Navigation Controller to a subview - objective-c

I'm currently working on a view based app for the iPad that has 3 seperate views on the main page. A custom menu up the top, a status list on the side, and a main view. The issue I am having with the main view is trying to add a navigation controller.
In AppPadViewController.h
#interface AppPadViewController.h : UIViewController {
MainViewController *MainView;
}
#property (nonatomic,retain) IBOutlet MainViewController *MainView;
And in AppPadViewController.m
#synthesize MainView;
- (void) viewDidLoad {
[super viewDidLoad];
MainView.navigationItem.title = #"Home";
UINavigationController *mainNavController = [[UINavigationController alloc] initWithNibName:#"MainView" bundle:[NSBundle mainBundle]];
self.MainView = [MainViewController alloc] initWithRootViewController:mainNavController];
}
And in the nib I have added the view where I would like it, and tied it in to the MainView, and then added the MainViewController and tied it to the File Owner and view.
When I run this, I get an 'Unrecognized Selector" error thrown on the initWithRootViewController line.
Can anyone see any problem with the code, or suggest a better way to add a navigation controller to a sub view?

You have your two view controllers reversed. Try something like this:
self.MainView = [[MainViewController alloc] initWithNibName:#"MainView" bundle:[NSBundle mainBundle]];
UINavigationController *mainNavController = [[UINavigationController alloc] initWithRootViewController:MainView];

Related

UIPopovercontroller in UISplitViewController

My detailviewcontroller is called myDetailVC , with tableVC which is just a table on the side of myDetailVC.
in myDetailVC, I have a button that is supposed to show a popoverviewcontroller. However, it crashes when I press it.
in my .h file:
#property (strong, nonatomic) UIPopoverController *masterPopOverController;
and .m:
- (IBAction)goToPDF:(id)sender
{
viewPDFViewController *MPPWV =[[viewPDFViewController alloc] initWithNibName:nil bundle:nil];
self.masterPopOverController = [[UIPopoverController alloc] initWithContentViewController:MPPWV];
[self.masterPopOverController presentPopoverFromRect:[sender frame] inView:[sender superview] permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
[self.masterPopOverController setPopoverContentSize:CGSizeMake(100, 100) animated:NO];
}
Everything is connected fine in my xib, since I tested it by making it push to a viewcontroller instead of a popover. Can someone help me with this?
First, it looks like you're loading it up with a view controller that doesn't have anything in it:
viewPDFViewController *MPPWV =[[viewPDFViewController alloc] initWithNibName:nil bundle:nil];
Try specifying a Nib name, if you have one. It's possible that you don't have a NIB for that view controller. If that's the case you probably have a designated initializer -init method that you should be calling on it. Do that instead of calling -initWithNibName:
Second, it doesn't look like you're retaining the view controller you're loading into the pop over. It's possible that they require strong references. Try retaining it via property (or an ivar):
#property (nonatomic, strong) viewPDFViewController * MMPPWV;
Then when you access it do so via self:
self.MPPWV = [[viewPDFViewController alloc] initWithNibName:nil bundle:nil];

Button that takes me to a new UIViewController based on the content of a TextField not working

I'm trying to make a button take me to a new UIViewController based on the content of a textField, but when I run it and hit the button (with the right condition in the text field to take me to the new UIViewController), the screen blacks out. This is what I wrote in my .h and .m files. Can anyone help me (Im using storyboards)
#interface ViewController : UIViewController
- (IBAction)boton:(id)sender;
#property (strong, nonatomic) IBOutlet UITextField *texto;
#end
#import "ViewController.h"
#import "ViewController2.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize texto;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)boton:(id)sender {
if ([texto.text isEqualToString:#"1"]) {
ViewController2 *vc1=[[ViewController2 alloc]init];
[self presentViewController:vc1 animated:YES completion:nil];
}
}
#end
As you say the screen is blacking out, I expect your viewController is getting initialised without a view.
To initialise with a view hierarchy from a xib(nib) file:
- (id)initWithNibName:(NSString *)nibName bundle:(NSBundle *)nibBundle
where nibName can be nil if it shares it's name with the View Controller, and nibBundle can be nil it the nib is in the main bundle.
i.e....
ViewController2 *vc2;
vc2 = [[ViewController2 alloc] initWithNibName:nil
bundle:nil];
where the xib file is named ViewController2.xib
To initialise from a storyboard:
UIStoryboard *storyboard = self.storyboard;
vc2 = [storyboard instantiateViewControllerWithIdentifier:#"ViewController2"];
(you need to set up a viewController in storyboard and give it a matching identifier)
To initialise with neither storyboard or xib, you should override your view controller's - (void)loadView, create a view and assign it to self.view.
Update
In answer to your comment - the UIStoryboard... and ViewController2 *vc2= ... code would go into your button code (in your case it you would replace / adapt the line containing vc1=.... It would look like this:
- (IBAction)boton:(id)sender {
if ([texto.text isEqualToString:#"1"]) {
ViewController2 *vc2;
UIStoryboard *storyboard = self.storyboard;
vc2 = [storyboard instantiateViewControllerWithIdentifier:#"ViewController2"];
[self presentViewController:vc2 animated:YES completion:nil];
}
You will need to have created a storyboard scene in your storyboard with a viewController whose custom class is ViewController2 and identifier is "ViewController2". The identifier name is arbitrary, but must match the identifier string you use in your code.
As you are using storyboards, an alternative way to do this is to create a modal segue from the 'ViewController' scene to a 'ViewController2' scene, give it an identifier, and use performSegueWithIdentifier in your button method.

Switch Active View Controller Programmatically

I have 2 views as part of my Navigation Controller.
I created a class for my Navigation Controller with a public method that certain actions on the first view will trigger to load the Detail View Controller. I am importing the Detail View Controller, but nothing in my code is working. I know the method is being called correctly because I'm logging it.
What am I doing wrong here?
#import <UIKit/UIKit.h>
#interface NearbyController : UINavigationController
- (void) nextpage;
#end
#import "NearbyController.h"
#import "DetailView.h"
#implementation NearbyController
-(void) nextpage {
NSLog(#"working");
DetailView *nextView = [[DetailView alloc] init];
[self pushViewController:nextView animated:YES];
}
#end
If you initialize a view controller programmatically you should use this init.
If you have set a storyboard ID you can do this
DetailView *nextView = (DetailView *)[self.storyboard instantiateViewControllerWithIdentifier:#"DetailViewControllerID"];
[self pushViewController:nextView animated:YES];
If you want to load from a XIB you can call
DetailView *nextView = [[DetailView alloc] initWithNibName:#"MyDetailViewControllerID" bundle:nil];
[self pushViewController:nextView animated:YES];
Hope it helps!
If you're using storyboards what you wanna do is setup the storyboard id in the identity inspector on your DetailViewViewController
Then you would wanna instantiate your view controller like so:
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
DetailView *nextView =[sb instantiateViewControllerWithIdentifier:#"DetailViewViewController"];
/* your identifier is your storyboard id*/
sb = nextView.storyboard;
Then you should be able to push your view controller.
Im still new to this but i hope this helps!

Jump between different viewControllers using UIButton?

I have a button that open another viewController(familyView) when clicked.
In familyView there is another button which suppose to bring me back to the mainViewController(ViewController.xib) but I don't know how to call the main viewController.
My method to call familyView
UIViewController* familyView = [[UIViewController alloc] initWithNibName:#"familyView" bundle:[NSBundle mainBundle]];
[self.view addSubview:familyView.view];
I hope you could help on how to call the main ViewController ? do I have to use the same method to call it? like this I mean:
UIViewController* mainView = [[UIViewController alloc] initWithNibName:#"viewController" bundle:[NSBundle mainBundle]];
[self.view addSubview:mainView.view];
If yes, is there a better way to implement this? in my demo project, I'm trying to make 7 views full with data and a button to go back and forth.
EDIT:
If I use UIView would that be best for me instead of using different viewControllers with their implementations and interfaces files?
My project will have views, and each view has data on it parsed from a different html page.
There are two method that can be used.
UINavigationController
Delegates
From your question it seems that a UINavigationController is the best option but I will show you both.
UINavigationController
When you load your mainViewController from your app delegate your going to need to wrap it in a nav controller like so:
AppDelegate.h
#property (strong, nonatomic) UINavigationController *navController;
AppDelegate.m
#synthesize navController = _navController;
//in didFinishLaunchingWithOptions:
UIViewController *mainViewController = [[MainViewController alloc] initWithNibName:#"MainViewController" bundle:nil];
navController = [[UINavigationController alloc] initWithRootViewController:mainViewController];
self.window.rootViewController = nav1;
[self.window makeKeyAndVisible];
Now in your MainViewController you have the convince of UINavigationController.
When you want to push to a child from a parent you can simply do:
ChildViewController *child = [[ChildViewController alloc]...];
[self.navigationController pushViewController:child animated:YES];
If you in your ChildViewController and want to go back simply do:
[self.navigationController popViewControllerAnimated:YES];
This is the "Drill Down" technique.
(I know "Drill Down" has more meaning than simply that but it provides a good frame of reference.)
Delegate
Now the other method that you have is to setup delegates between the classes. So if your in childView and need to call your parent, you will have a channel to do so.
In your MainViewController.h setup it like so:
#import <UIKit/UIKit.h>
//This is our delegate
#protocol TalkToParentDelegate <NSObject>
//This is our delegate method
- (void)helloParent;
#end
#interface MainViewController : UIViewController <TalkToParentDelegate>
...
..
#end
In your MainViewController.m make sure add the delegate method.
- (void)helloParent {
NSLog(#"Hello child, let me do something here");
}
In your ChildViewController.h setup it like so:
#import <UIKit/UIKit.h>
//Add header of class where protocol was defined
#import "MainViewController.h"
#interface ChildViewController : UIViewController
//Create a property we can set to reference back to our parent
#property (strong, nonatomic) id <TalkToParentDelegate> delegate;
#end
Now, in your MainViewController.m , whenever you present your ChildViewController do this:
ChildViewController *child = [[ChildViewController alloc]...];
//Set the delegate reference to parent
child.delegate = self;
//present the view
Last but not least, no when you in your child you can call methods on your parent (MainViewController) like so:
[self.delegate helloParent];
So here are two methods that you can use.
I would like to note however, you can use these together. Say you had a UINavigationController but still needed a child to talk to its parent, you can setup a delegate so that's possible.
Hope this helps.

initWithNibName : I have no scroll and no navigation bar?

So I've a button with a IBAction heading to another ViewController by its initWithNibName method. Everything is embedded in a NavigationController.
I also created a .xib for this ViewController, here is a quick screenshot :
Here is my code :
.h
#interface ModeEmploiController : UIViewController
{
IBOutlet UIScrollView *scrollView;
UITextView *vueOffres, *vueInfos, *vueGrilles;
}
#property (nonatomic, retain) IBOutlet UIScrollView *scrollView;
.m
#implementation ModeEmploiController
#synthesize scrollView;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
{
[scrollView setScrollEnabled:YES];
[scrollView setContentSize:CGSizeMake(320, 529)];
// Here I define vueOffres, vueInfos and vueGrilles and for each of them :
[self.view addSubview:vueGrilles/vueInfos/vueOffres];
}
}
But when I run my app, my scroll isn't enabled and I don't have the navigation bar of my navigation controller. What's happening?
add another view inside the ScrollView i called mine content view. the do
self.scrollView.contentSize = self.contentView.frame.size;
for the navigation bar you need to have a uinavigation controller and make your controller the rootviewcontroller of the navigation controller. like this
-(IBAction)MyButton:(id)sender
{
MyViewController *controller = [[MyViewController alloc] initWithNibName:#"MyView" bundle:nil];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:controller];
[self.navigationController presentModalViewController:navController animated:YES];
}
Remove your ModeEmploiController from xib, but keep its child View and ScrollView.
now click on File's Owner and put ModeEmploiController from Identity inspector in right panel.
Now right click on File's Owner and connect property of view to View and scrollView to ScrollView.
Your initialization code is in the wrong method.
Since you are using Storyboards, your view controller is being unarchived from a nib file. The correct place to initialize the controls is in the awakeFromNib method.
Make sure that you have set up an IBOutlet property for your scroll view and hooked it up in the Storyboard, and then:
- (void)awakeFromNib {
[self.scrollView setScrollEnabled:YES];
[self.scrollView setContentSize:CGSizeMake(320, 529)];
// Here I define vueOffres, vueInfos and vueGrilles and for each of them :
[self.view addSubview:vueGrilles/vueInfos/vueOffres];
}
That just leaves the problem of the subview that you are adding. What is vueGrilles/vueInfos/vueOffres? You should create this view properly within the viewDidLoad method and add it as a subview there instead of in this initialiser.