addSubviews from xib file contain two or more Custom View - objective-c

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).

Related

How to embed nibs programmatically?

I have a UIViewController with an UIScrollView in it.
Then I created a new UIView subclass with some properties that I want to programmatically add in this UIScrollView until my data ends.
Something that should look like this picture:
I have read other topics that does that by creating a view and setting its class to the custom view subclass, but I want to do it programmatically and its not working.
how would I do that?
From your image it looks like you're looking to load views from a nib and add them as subviews of your UIScrollView. To do this have a look at the UINib documentation.
You want to create your nib and set it's main view to be an instance of your UIView subclass then load the nib in viewDidLoad of your viewController, and add the nib's views as subivews of your scrollview (which I'm assuming is a subview of your viewController's view).
You can instantiate a nib with instantiateWithOwner:options:.
This method unarchives each object, initializes it, sets its
properties to their configured values, and reestablishes any
connections to other objects
To get the array of views from a nib you do something similar to:
UINib *myNib = [UINib nibWithNibName:#"myNib" bundle:[NSBundle mainBundle]];
NSArray *viewsFromNib = [myNib instantiateWithOwner:nil options:nil];
I'll assume we're inside a UIViewController and we're somewhere in (or after) viewDidLoad. You would then use the array from above and add the views as subviews of your scrollview. You may need to set the frames of these views to place them properly, but that should be trivial.
UIView *aView = [viewsFromNib objectAtIndex:0];
[self.scrollView addSubview:aView];
I hope that sets you in the right direction.
Edit:
If you want more information you may need to read deeper into how nibs work to manage your expectation. Linked with the UINib documentation is the 'Resource Programming Guide' in particular the nib section
André, this can be done with relative ease. make sure to import the class that you want to embed. then to create them with your normal
ClassName *subview=[[ClassName alloc]init];
[subview.view setFrame:CGRectMake(x,y,width,height)];
[self.view addSubview:subview.view];
which will add it to the x,y coordinates you specify with the size specified by your width, height. you can do this in the viewDidLoad or whenever you need them to be created.

Cocoa - Display xib on another xib

Can anyone tell me how (or direct me to info on) displaying a .xib (nib) on another .xib (nib).
How ever I wish to place it so I can programically move it around the main nib sort of like this (which obviously doesn't work)
- (void)drawRect:(NSRect)dirtyRect
{
NSRect customView = NSMakeRect(pos1, pos1, 200, 100);
[[NSBundle mainBundle] loadNibNamed:#"secondXib" owner:self];
NSRectFill (customView);
}
And I wish to do this for Mac OS X (Not iPhone). (By the way using xCode 4 incase it makes a difference)
You can easily load a view from another nib using NSViewController. In your nib you should just set File's Owner's custom class to NSViewController and hook up the view outlet of File's Owner to point to the view you want to load. You can then just do this:
//create an NSViewController and use it to load the nib
NSViewController* vc = [[NSViewController alloc] initWithNibName:#"YourNibName" bundle:nil];
//get the view from the view controller
NSView* loadedView = [vc view];
//release the view controller so we don't leak
[vc release];
//add the view as a subview of your main view
[mainView addSubview:loadedView];
//position the view
[loadedView setFrameOrigin:NSMakePoint(100.0, 100.0)];
You don't need to do anything in drawRect:. The subview will draw itself, and drawRect: will be called automatically if you move the subview.
You should read the View Programming Guide for Cocoa. It is critical to understanding how views work, and it is clear from your question that you do not yet have that understanding.
You should also read the Cocoa Drawing Guide.
Thanks a lot,
Another alternative ( which is basically the non programming way of doing it ), is to add a NSViewController object in your first xib, and set it to you use the nib name that you specify.
In your second xib, don't forget to set the class name in the "custom class" field on the view ( and NSViewController on file's owner ) else that won't work.

NSViewController not being created

I am building a cocoa application with one main window controller with a xib. That xib contains many custom view classes. I would like to add an NSViewController to the xib, but i'm running into some trouble.
In interface builder I can drag the NSViewController into the xib, assign it its custom controller class, and assign its view to the appropriate view in the xib. Here's the problem: neither the initWithNibName:Bundle: or loadView get called.
What am I missing?
EDIT:
People seem to be misunderstanding the question so I'll clarify.
The window already has a view controller. What I am seeking to do is assign separate view controllers to several of the subviews. I need to know how to associate my NSViewController subclass with the appropriate NSView subclass (which is a child of the main window).
Or in other words, I am trying to use multiple NSViewController subclasses to controll many different custom views (one each) within a single .xib file. Those controllers and subviews have their own .xibs which should ultimately become visible in the same window.
The pattern I use for NSViewController is to have a xib per view controller. Then, when you need that view controller you alloc it and use the initWithNibName:Bundle: method. As soon as you use its view, loadView will get called.
Example:
self.editViewController = [[[MyEditViewController alloc] initWithNibName:#"MyEditViewController" bundle: nil] autorelease];
[self.window setContentView: editViewController.view];
I used to get stuck with that as well and gave up on that thing - the blue circle with a white bordered view in it from the IB palette. I now create my controllers from code and only set a reference in IB to the owning controller class via the file owner: right click the file owner, enter the class name in the Identity inspector and then make a connection from the file's owner view to the view.
In your code you then do at an appropriate initialisation point:
[self setMyViewController = [[MyViewController alloc] initWithNibName: #"MyView" bundle: [NSBundle mainBundle]]
For your specific case this could be in windowDidLoad method when your window is loaded from its nib and ready for work. You can then add the view to your windows content view. Also you might want to consider to have a 1:1 relation between view and view controller. It makes life a lot easier in terms of maintenance.
EDIT: Like #pcperini suggests in his comments you can use the palette component, but you'll still need to instantiate the controller in your code. If you want to use the palette component, create a property in your main controller or AppDelegate:
#property (...) MyViewController *myViewController;
Add the line of code to actually create the controller (see above). Then, using the bindings inspector bind the palette component to the myViewController property.
So, what you are missing is that you are actually not instantiating the controller object.
EDIT 2: Here's the code (the awakeFromNib is the method of the top controller). It creates two child controllers each handling a different subview:
- (void) awakeFromNib {
[[self startEndTopicHeader] setHeader: #"Event timeline boundary"];
[[self startDateHeaderView] setHeader: #"Event (start) date"];
[[self endDateHeaderView] setHeader: #"Event end date"];
[self setStartDateViewController: [[EventTimeViewController alloc] initWithNibName: #"EventTimeView" bundle: [NSBundle mainBundle]]];
[[[self startDateViewController] view] setFrame: [[self dummyStartView] bounds]];
[[self dummyStartView] addSubview: [[self startDateViewController] view]];
[[self startDateViewController] setParentController: self];
[self setEndDateViewController: [[EventTimeViewController alloc] initWithNibName: #"EventTimeView" bundle: [NSBundle mainBundle]]];
[[[self endDateViewController] view] setFrame: [[self dummyEndView] bounds]];
[[self dummyEndView] addSubview: [[self endDateViewController] view]];
[[self endDateViewController] setParentController: self];
}

Loading a view from another controller and nib

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

Design an NSView subclass in Interface Builder and then instantiate it?

So I have an NSTabView that I'm dynamically resizing and populating with NSView subclasses. I would like to design the pages in IB and then instantiate them and add them to the NSTabView. I got the programmatic adding of NSView subclasses down, but I'm not sure how to design them in IB and then instantiate them.
I think I got it. Let me know if this is not a good thing to do.
I made a new xib file, set its File's Owner to be an NSViewController and set its "view" to the custom view I designed in the xib.
Then you just need:
NSViewController *viewController = [[NSViewController alloc] initWithNibName:#"MyViewXib" bundle:nil];
NSView *myView = [viewController view];
#toastie had a really good answer. Mine is similar, but requires a bit more explanation.
Let's say you've already got a controller object and you don't want to instantiate a new controller object just to get at a view, and let's say that you're going to need multiple copies of this view (for example, you've designed a custom UITableViewCell in IB and you want to instantiate it again and again from your UITableViewController). Here's how you would do that:
Add a new IBOutlet to your existing class called "specialView" (or something like that). It may also be helpful to declare it as a (nonatomic, retain) property.
Create a new view xib called "SpecialView", and build the view however you like.
Set the File's Owner of the view to be your controller object.
Set the specialView outlet of File's Owner to be the new view.
Whenever you need a new copy of the view in your code, you can simply do the following.
(gratuitous text to get formatting working properly)
NSNib * viewNib = [[NSNib alloc] initWithNibNamed:#"SpecialView" bundle:nil];
[viewNib instantiateNibWithOwner:self topLevelObjects:nil];
[viewNib release];
NSView * myInstantiatedSpecialView = [[[self specialView] retain] autorelease];
[self setSpecialView:nil];
Yes, it's a bit more code than other ways, but I prefer this method simply because the view shows up in the designated IBOutlet. I retain and autorelease the view, because I like to reset the outlet to nil once I have the view, so it can be immediately ready to load a new copy of the view. I'll also point out that the code for this is even shorter on the iPhone, which requires one line to load the view, and not 3 (as it does on the Mac). That line is simply:
[[NSBundle mainBundle] loadNibNamed:#"SpecialView" owner:self options:nil];
HTH!