Loading a view from another controller and nib - objective-c

I have a situation where a Panel is loaded with a view, but when a button is clicked I need to switch to a view that is in a different nib file, and that has a different controller.
So say I have Foo.nib, and Bar.nib. Foo.nib is a panel and view, Bar.nib is just a view. In FooController I have a line like:
[NSBundle loadNibNamed:#"Foo" owner:self];
but I think I also need:
[NSBundle loadNibNamed:#"Bar" owner:BarController];
And when the button is clicked I switch the View in FooController, but all of the BarController GUI elements are not handled by BarController. Is this the right idea? If so, I'm not able to get the Bar nib to load even though BarController is in the Foo nib.

You probably want to make 3 nib files: one for Panel, Foo and Bar. Then you can make FooController and BarController subclasses of NSViewController and create them like so
FooController *fooController = [[FooController alloc] initWithNibName:#"Foo" bundle:nil];
BarController *barController = [[BarController alloc] initWithNibName:#"Bar" bundle:nil];
Whenever you need the view to be placed in the panel you would just do
NSView *fooView = [fooController view];
[panelView addSubview:fooView];
or you could swap the views using replaceSubview:with:
There's a more complete example here

Related

iOS crash when pressing button from manually loaded viewcontroller

I programmatically instantiate a UIViewController from a xib, add it as a child VC to an existing main view, then add the child VC's view (which contains a button) to my main view. The view with the button displays just fine, but when I press the button, the app crashes with an "unrecognized selector" message.
I created the XIB by creating a custom subclass of a UIViewController ( File - New - Cocoa Touch class, selecting a subclass of UIViewController, and asking Xcode to also generate the XIB file). I then placed a button on that XIB, and hooked it up to the newly created UIViewController subclass. The XIB file's owner is set to the name of the new class.
So it looks to me like the ButtonPushed action message doesn't get send to my custom UIVC, and is going instead to the generic UIViewController - which rightly doesn't understand the ButtonPushed message.
How do I make sure that the action message sent when the button is pressed in fact goes to my custom UIViewController?
This is the code in my awakeFromNib method for the main view (main view is from Main.storyboard):
UIViewController *vc2 = [[UIViewController alloc] initWithNibName:#"ButtonVC" bundle:nil];
vc2.view.frame = CGRectMake(90, 140, 50, 200); //dont obscure the main view completely.
[self addChildViewController:vc2];
[self.view addSubview:vc2.view]; //vc2.view has a button, which shows up fine
[vc2 didMoveToParentViewController:self];
I've managed to get the equivalent functionality by creating a storyboard just with the button, and programmatically loading that, then instantiating my buttonViewController, adding it and its view as a child VC to my main view. That works just fine, but it seems to me like I should be able to achieve this with "only" a XIB.
Try this:
UIViewController *vc2 = [[ButtonVC alloc] initWithNibName:#"ButtonVC" bundle:nil];
And also make sure that the class in your xib for the view controller is set properly (see my answer here)

addSubviews from xib file contain two or more Custom View

I have xib with two CustomView (NSView *one, NSView *two),how i addSubview in AppDelegate?
self.content = [[ContentViewController alloc]
initWithNibName:#"ContentViewController"
bundle:nil];
[[[[self vertical] subviews] objectAtIndex:1] addSubview:[_content one]];
This way don't work.
Each view should be in it's own NIB file, as the NSViewController only has a single view instance variable.
So the answer is to split each view into it's own NIB; set the custom class correctly and then set the File Owner to NSViewContoller and connect the view from the controller to the custom view.
You then load each separately and add their views whereever you like (taking care to keep a reference to the NSViewController used to load the view).

How to create simple table view controller in code only

I need the same type of table view controllers in my app many times and would like to create a more generic table view controller which I can use over and over again.
These table view controllers are quite simple and show only the contents of an array, put a check mark to the selected table view cell and return the index of the selected table view cell to the calling view controller after the Done button in the toolbar has been tapped.
Currently I create each one of these table view controllers directly in Storyboard and instantiate them by using segues.
Would it be possible to do this in code only (without using Storyboard or xibs)?
What would be the best way to instantiate and push them onto the navigation controller stack (each one will be shown in a view controller).
It's trivial to do this in code. You create your view controller class just like you normally would (extend UITableViewController). Implement all of the same table view data source and delegate methods. All of that is the same.
When you want to use the table view controller you just do:
MyTableViewController *vc = [[MyTableViewController alloc] init];
[self.navigationController pushViewController:vc animated:YES];
I would define your MyTableViewController init method like this:
- (id)init {
if ((self = [super initWithStyle:UITableViewStyleGrouped])) {
// any other initialization
}
return self;
}
BTW - I have an app with over 100 view controllers in it and I've never used Interface builder or storyboards. It's all code.
Would it be possible to do this in code only (without using Storyboard or xibs)?
Yes. Anything you can do in a storyboard or .xib file, you can do in code:
MyViewController *vc = [[MyViewController alloc] initWithNibName:nil bundle:nil];
Note: the default behavior for a view controller is to load its view from a .xib with the same name as the view controller's class when you pass nil for the .xib name, e.g. MyViewController.xib for the example above. So the line above creates the view controller in code, but will still load the view from the .xib. If you want the view created programmatically as well, override -loadView.

How to addsubview to a view on class1 from class2?

I'm trying to do a really simple thing - I've got a main Xib file for the whole app and another Xib file for a small view.
I want the small view (Xib called "additionalView.xib") to appear in the first Xib ("ViewController.xib").
I have succeeded to do so in the "ViewController.m" but I want more - I want to do it from "additionalView.m"
There is a method I created called "openView:" in "additionalView.m" and it looks like this:
-(IBAction)openView:(id)sender
{
ViewController *vc = [[ViewController alloc] init];
NSArray *nibObjects = [[NSBundle mainBundle] loadNibNamed:#"additionalView" owner:self options:nil];
UIView *nibView = [nibObjects objectAtIndex:0];
[vc.view addSubview:nibView];
}
The method is being called and the lines are being read by the debugger - but nothing happens.
No crash - No error - No small view in bigger view.
Why is that?
I know that the last line is probably what's
screwing everything up but i don't know how to put it correctly.
Your problem is that ViewController *vc = [[ViewController alloc] init]; creates a new view controller. Because it's new, it's not the one that already exists in the view controller hierarchy that's managing the display.
Your method needs to access the existing view controller. How it does that depends on your app's structure and which object has a reference to the original controller object.
Try
[self.view addView:view.vc];
However, I'm not sure what is you view structure here. You say your -(IBAction)openView:(id)sender is in your "additionalView.m", but it is not the main view controller, correct? You need to do this in the main controller, so basically move the openView: method to your ViewController.m
And you normally need a separate view controller for each view to keep things neat and separate, so the additionalView.m should be an instance of UIViewController, which you can then create from your main view as follows:
-(IBAction)openView:(id)sender
{
AdditionalView *vc = [[AdditionalView alloc] initWithNibName:#"additionalView"];
[self.view vc.view];
}
You have options ... First you don't need to create a view controller vc if you just need the view . Create a uiview and add it .
Option 1: pass a ref to the app vc as suggested above and then :
[appVC.view addsubview:additionalView]
This will add it to main.
Use a view controller manager / ref in the app delegate that you can refer to as delegate and add your view to the current showing view.
Hope this helps

Switch views - UIViewController to UITabBarController

I have made a very simple Navigation based app (UIViewController). The view has a single button on the Main RootViewController.
Next, I made 2 classes: TabOneViewController, TabTwoViewController. All good. I then created a new Class TabBarViewController. I opened up the NIB file and dropped on a ``UITabBarController onto it. The two tabs it creates in it by default were assigned (respectively) to my TabOne and TabTwo view controllers.
strong text
Then in my TabBarViewController, I made an IBOutlet for a UITabBarController, synthesized it etc etc. I linked it up in Interface builder via the "files owner".
In the RootViewController, I linked the button to my "pushView" method, and in this pushView method, I have the following code:
- (IBAction) pushView {
TabBarViewController *controller = [[TabBarViewController alloc] init];
[self.navigationController pushViewController:controller animated:YES];
[controller release];
}
The end result is it DOES push a view, but I cannot see the tab bar at the bottom, let alone any of the pages I've added to the controller.
What am I doing wrong? Why can't I link it in IB?
I am not 100% sure if that's allowed.. because you already have one tabBarController as rootViewController, and you dropped one more tabBarController as first tab controller, tabs ll overlap, considering amount of real estate you have on your iPhone, it make sense to not allow a tabViewController inside another
First, you need to allocate your view controller with your nib:
TabBarViewController *controller = [[TabBarViewController alloc] initWithNibName:#"YourNibName" bundle:nil];
Secondly, in IB, click the UITabBarController and go to the identity inspector and make sure you select your custom class. That said, unless you are overriding or adding some functionality you probably don't need the custom class at all, simply use a UITabBarController directly:
UITabBarController *controller = [[UITabBarController alloc] initWithNibName:#"YourNibName" bundle:nil];