Using one nib file for multiple NSViewControllers - objective-c

I have one NSTableView nib that contains a number of cells that will be reused throughout 3 different NSViewControllers. The NSTableView and cells function in the same way and look similar but present different data in each of the different views.
Right now I can set the File's Owner to one of the NSViewController classes, but not all of them meaning I'd have to duplicate the nib 3 times. Given that I'm loading with initWithNibName:bundle I don't see any way to set the File's Owner first either.
How can I use one nib with multiple File's Owner for NSViewControllers?
Any ideas?

Have you tried simply NSViewController or a subclass of it that is an abstract superclass of your view controllers?
One subclass could even be sufficient if the differences between your instances can be managed with conditional logic in the subclass.
Either way, it sounds like you have some refactoring to do, but minimal.

I am an iOS developer not OSX but we also face this problem. In our case I would have used a UIView class(surely you will have NSView kind of class) and then added table on that class and made File's Owner of the table to that view class.
I can reuse this class whenever I want in any view controller by adding this view on that controller and changing its data set.

Related

Nib vs. View - How do they interact/overlap each other?

I'm very new to objective-c and it seems my question is so basic there's nothing concise on it around (I just end up more confused by reading things).
When you create a .xib file, you link it to a controller (usually, I think). At the same time, you can do things you can do in .xib by defining views in code. I thought I understood part of it when I realized most of the items you drag onto a .xib are view objects. I guessed from there that .xib were somehow just representing real code for views. Is that accurate? Or am I completely wrong? I really have no idea.
Xib files do not represent real code for views, only the structure of the view's data. Each xib (or a storyboard) has enough information to do all of the following:
Instantiate elements of the view
Set properties of individual elements of the view
Connect elements of the view in a hierarchy
Connect "outlets" of objects in the Nib to properties or variables of views in your code.
However, there is no "real code" there, only the metadata. Cocoa has enough smarts to build and connect the objects, but the actual code is always in your .m files.
A view controller manages a view which is made up of many subviews. While, every view can have only one superview at most. ( superview is nil for the top-most view). This is called the view hierarchy.
The top level view in a hierarchy can be defined using pure code, or with Interface Builder, which produces a xib.
Its useful also to explore the relationship of view controllers to each other. Within one application window, there can also be several view controllers, each managing their own top-level view. This is called view-controller containment. An example of this is a UINavigationController or tab-bar controller. . .in more complex apps it is common to set up your own root controller that manages this aspect of controller heirarchies. (Eg swipe to reveal a navigation controller, which is under the main content cotroller).
A XIB describes arbitrary objects that conform to NSCoding but is usually used to layout a view hierarchy. So it'll be mostly UIViews, usually with a UIViewController.
However they're purely data. No code is generated. The system reads the XIBs and creates the objects purely as a data-reading exercise.
Objective-C has a fully reflective runtime — you can lookup classes by name as a string and can call methods on them the same way, without even knowing whether the method really exists in advance. Interface builders that secretly write code, such as Microsoft's in Visual C++, tend to do so because there's no way they could establish whatever you've described purely by parsing data.

StoryBoard handling inherited view controller

I am new to storyboard. I used to make my view using code. I have a question.
I created a view controller
#interface FunctionViewController : UIViewController
And I have use my code to add
a full screen button (alpha : 0.5)
a popup-like view in the middle (not full screen)
Then I created another Viewcontroller
#interface PlayFunctionViewController : FunctionViewController
and add some views on the popup-like view
I want to recreate these stuff by using storyboard.
How can I build these using interface builder and storyboard so that
I don't need to layout the full screen button and the popup-like view in every subclass of FunctionViewController?
You can't inherit the layout of a superclass in a subclass in a storyboard, i.e. if you visually lay out elements in a view controller in a storyboard and connect them to code, subclasses of that view controller, and even other instances of the same class, will have to be laid out individually, and will not automatically be populated or updated.
In other words, in a storyboard, you will have to manually lay out and connect all your interface elements in every individual instance and subclass that you add to the storyboard. This gives you flexibility in that you can reuse multiple instances of the same class throughout your app and lay them out differently, but it does not give you the ability to inherit layouts.
If you want to inherit your layout in subclasses, do your layout programmatically in the viewDidLoad of your superclass, and then all of your subclasses will have those interface elements, even if you design and lay them out in your storyboard (they will not be visible in the storyboard, but they will appear when you build and run your app).
Basically, if you want to have interface elements that are the same in a class and all its subclasses, create them programmatically, and they will exist in all instances and subclass instances, even if you create and design the instances themselves in your storyboard.
You can mix code and storyboard, so you can create some elements in your storyboard, but others that need to be present in all instances and subclasses, in code.
I ran into a similar issue, and though it was time consuming but creating a delegate and reusing it in multiple view controllers was a much better solution. Although that beats the whole point of 'Inheritance'.

How to access the XIB's owner?

The issue i am facing deals with multiple views, each needing to communicate with one another. I chose to use the File Owner for this, but can't seem to be able to access the already loaded instance of it from inside of views.
Each rectangle represents its own view
Activity will happen on "Some View", where user's event will cause Labels in top view to be updated
Event will not be triggers by a button click of anything like that. No outputs are set up to establish relationships between the views
No outlets are set up between the views
Outlets are setup however between top Views (with Labels) and File Owner (UIViewController).
Ultimately, i'd like to update label in view 1 from view 2.
Then the bar moves, I want labels to change
At this time, i believe a reasonable solution would be to ask the File Owner to make a change for Labels. From the "Some View", i'd like to call the File Owner and make a request.
From the stand point of the any view residing as part of the nib, how can i know who the "File Owner" of this nib is?
In the Interface Builder, File Owner maintains the IBOutlet to UILabels of the view.
You need to define a delegate (or whatever you like to call it) outlet in your Puzzle1 class and link this to File's owner in the nib. This will give you a pointer to the instance of the view controller that currently owns your view. If you set the type of the delegate to your viewcontroller subclass, then its methods and properties will be available to you from within the view.
This sounds potentially horrendously messy and is probably better solved by using NSNotifications.
But anyways, did you know there's a UINib class? Perhaps you could subclass that and keep track of the owners (which get passed in it's instantiateWithOwner: options: method) as things are loaded.
http://developer.apple.com/library/ios/#documentation/UIKit/Reference/UINib_Ref/Reference/Reference.html

How to bind nib custom view to a NSVIew subclass

I have a simple requirement.
On Click of a + button, I am trying to add a custom view to a SplitView.
I have created a class MyCustomView which is a subclass of NSView
In the applications nib file, I have a custom view which contains the buttons etc.
Now How to allocate a new MyCustomView every time ?
Is there an example to do this?
I am hoping something like
MyCustomView *v1 = [[MyCustomView alloc] init];
..
..
[splitView addSubView:v1];
[splitView addSubView:v2];
...
Please help
It's hard to tell exactly what you're describing based on your description but let's see if I understand you. You want to add a "copy" of your custom view assembly into a split view each time "+" is clicked, right?
The absolute best way to do this is to put the custom view assembly that will be copied (the "prototype") in its own xib. For each object you want to represent, you will instantiate a new copy from the xib and give it to some owner then add it to some parent view (a split view in your case ... odd for an unlimited number of views, but I don't have enough detail to say otherwise).
So. In the modern Cocoa world, such a view assembly should likely have its own view controller (NSViewController). This makes things easier for you since the xib's File's Owner will be an instance of your MyCustomViewController, whose -view is connected to the main container view in the xib (your custom view with all its subviews) and whose -representedObject is set to whatever model object your custom view represents. Your app will then maintain a list (an array or a dictionary, perhaps) of all the view controllers for the model objects. See this SO question/answer for a run-down of how to load from nibs/xibs.
This is basically how an NSCollectionView works (though the views must all be the same size - might not work for you). The collection view corresponds to your split view in this case; NSCollectionViewItem corresponds to your MyCustomViewController (and in fact on 10.5 and above NSCollectionViewItem is a subclass of NSViewController); your custom view is the collection view item's main -view. For each model object in its collection, it instantiates an NSCollectionViewItem and loads the view prototype from a xib (ideally, but this is optional), and uses this to set the item's view, then it sets the item's represented object (the model object).
I hope this clarifies things a bit. You've got some reading to do in order to understand enough of the nuts and bolts, but if you're still stuck, you might try editing your question to clarify or opening a new, more specific question.

Accessing the stringValue from NSTextFields on different NIBs

I'm having an extremely difficult time trying to access information from an object (e.g. an NSTextField) that is located on a NIB other than my "MainMenu.nib".
My current setup:
I have a MainMenu.xib that contains only a toolbar at the top and an NSView. I have four other .xib files containing custom NSViews and each of their File Owner's are assigned to a NSViewController subclass which I have created for each. My MainMenu.xib contains an object that is set to my WindowController subclass that takes care of swapping the fours views into the NSView on my MainMenu.xib. All of this works fantastic.
Where I have a problem:
I have another class that acts as the brains to my application which sends and receives data from an online server, all of the methods I have created rely on inputs from the user that are located on the individual .xibs that swap into my MainMenu.xib's NSview. Unfortunately I have no idea on how to grab the information from the NSTextFields, textViews, etc. that are located on my individual .xib files.
What I've tried:
I have tried setting the File Owner's of the four individual .xibs to my "brains" class and connecting outlets defined in my "brains".h, but when I call [textField stringValue] I receive a NULL response. I'm thinking this is because I'm creating multiple instances of my "brains" class but not totally sure.
Any help on accessing information from textFields from other nibs would be a great benefit, thanks in advance.
each of their File Owner's are
assigned to a NSViewController
subclass which I have created for each
I think the easiest way (not the best way) is that your brain contains all 4 NSViewController subclass and you leak the information of the UITextField out using the property and then you can access them