views:

418

answers:

2

As I move more and more of my UI construction from XCode to IB there is one remaining hurdle I need to clear.

Currently, I create my custom viewControllers in XCode with custom initializers. They typically have a bunch of ivars that are set during initialization via passed params. I would really like to move as much of this as I can to IB.

Could someone carefully explain to me - or, better, point me to code - how to replicate the XCode approach of passing params via custom initializer in IB - presumably via IBOutlet.

Thanks in advance.

Cheers, Doug

UPDATE:

A typical scenerio is my AppDelegate will go out to the network, grab some data - NSMutableData, and then pass a reference to a root viewController - typically a TableViewController - that is pushed on the viewController stack of an navigationController.

When a cell is selected an secondViewController is alloc/init'ed and a subset of the data is passed to it. The secondViewController goes to the network for a bit more data, builds a view hierarchy, hands bits of the retrieved data to each subview and then each subview is messaged with setNeedsDisplay to process the data.

It is this hierarchical data passing that I want to hand off to IB is possible.

+3  A: 

You can still have a custom initializer. However, inside this initialized you'll call -[initWithNibName:@"yourNibName" bundle:bundle]. You will connect your UIKit related instance variables (UILabel, UIButton, etc.) in Interface builder and therefore won't have to instantiate those objects in your initializer. Other instance variables (strings, dictionaries, custom objects, etc.) you'll instantiate and set in your initializer.

Also, keep in mind that manipulation of your UIKit related variables such as setting label text, or setting the position of a UIView, should be done in the viewDidLoad method since these objects may not have been fully created at the time initializer is executing.

Let me know if you need more information.

Justin Gallagher
Thanks Justing. Yah, that's pretty much the approach I have been using. I was hoping there was a way refactor the setup I'm doing with non-UIKit ivars - NSMutableData, NSMutableArray, etc. - in viewDidLoad to IB. It sounds like that is not possible.
dugla
No problem. Just to be clear, you may want to do the initialization of those vars in your custom initializer instead of viewDidLoad.
Justin Gallagher
Justing, Actually what I tend to do is wait until viewDidAppear:. What I do is show a spinner while I asynchronously get data from the network, cook the data a bit on return, hand the cooked data to my subviews, call setNeedsDisplay on my subviews, and turn off the spinner.
dugla
That definitely makes sense for data that is being pulled from the network.
Justin Gallagher
+1  A: 

Lets say we have MyViewController which extends UIViewController and MyViewControllerParameter which is one of our custom objects we pass into MyViewController on initialization. MyViewController has an IBOutlets of type MyViewControllerParameter defined in it. We want to put MyViewController into another containing view, ParentView.xib. ParentView.xib is owned by ParentViewController.m and created elsewhere. We double click ParentView.xib in XCode to launch Interface Builder. We then drag an "object" from the Library View (I believe you open the library view with Cmd+Shift+L if its not open by default) onto the Document window. (This is the window activated by Cmd+0.)

An "Object" is an arbitrary widget found in the library (identified by a solid gold cube icon) that can represent anything in your project. After we've placed the new object into the document window, we type Cmd+4 to open the Indentity Inspector Window. In the top text field we can type the name of our view controller parameter, "MyViewControllerParameter". Next we find the ViewController widget in the library and drop it into the document window. We open the Attribute inspector (Cmd+1) and set the nib name to "MyView.xib". This should cause CocoaTouch to load MyViewController using the definitions in "MyView.xib".

Open the identity inspector and set the class attribute to MyViewController. Last we right click or control click (or two finger tap if we've correctly configured the trackpad on our MacbookPro) MyViewController in the document window. That will open a window showing all of the IBOutlets in MyViewController. Drag a line from the little open circle next to the MyViewControllerParameter outlet and drop it on the MyViewControllerParameter object sitting in the document window. Connecting these dots is how you set parameters between objects using interface builder.

Cliff
A little formatting (a line break or two, for instance), would really make your answer a *lot* easier to read.
Sixten Otto
Thanks Cliff. However, as I'm beginning to realize, IBOutlets can only be used with NSControl subclasses. I'm dealing primariy with NSMutableData, NSMutableString, and NSMutableArray. Containers and strings. These are not NSControl subclasses.
dugla
That's news to me. I thought you could plug any object into an IBOutlet so long as it's available in the xib file. I could be wrong, however.
Cliff