11

I'm trying to keep things organized and create hierarchy of views for my app. So for instance I want to create a custom view to display some text, another custom view to display progress and then use all those views in the main view created with View-Based Application template.

I know how to create it programmatically - you create UIView subclass, implement drawRect method, place an empty UIView in Interface Builder and chance it's Class to my custom class. My problem is that I want to create those custom view's in Interface Builder instead programmatically.

So far I've created UIViewController controller with XIB file and in viewDidLoad method of view controller from the template I create that custom view controller instance and add it's view as a subview of that empty UIView added in Interface Builder (the same you would change Class in programmatic approach).

It works, but it's more of a hack for me and it's hard for me to believe that there isn't a better method where I could add those custom views in interface builder without having to implement viewDidLoad method and create controllers and add their views inside of that method.

shw
  • 614
  • 6
  • 14

4 Answers4

1

For this to work, you have to create a plug-in for Interface Builder that uses your custom control's class. As soon as you create and install your plug-in, you will be able to add by drag and drop, instances of your view onto another window or view in Interface Builder. To learn about creating IB Plugins, see the Interface Builder Plug-In Programming Guide and the chapter on creating your own IB Palette controls from Aaron Hillegass's book, Cocoa Programming for Mac OS X.

Here is the link to the original author of the accepted answer to a similar question.

Cœur
  • 37,241
  • 25
  • 195
  • 267
luvieere
  • 37,065
  • 18
  • 127
  • 179
1

This was originally a comment in Ratinho's thread, but grew too large.

Although my own experience concurs with everything mentioned here and above, there are some things that might ease your pain, or at least make things feel a little less hack-ish.

Derive all of your custom UIView classes from a common class, say EmbeddableView. Wrap all of the initWithCoder logic in this base class, using the Class identity (or an overloadable method) to determine the NIB to initialize from. This is still a hack, but your at least formalizing the interface rules and hiding the machinery.

Additionally, you could further enhance your Interface Builder experience by using "micro controller" classes that pair with your custom views to handle their delegate/action methods and bridge the gap with the main UIViewController through it's own delegation protocol. All of this can be wired together using connectors within Interface Builder.

The underlying UIViewController only needs to implement enough functionality to satisfy the "micro controller" delegation pattern.

You already have the details for adding the custom views by changing the class name and handling the nib loading. The "micro controllers" (if used) can just be NSObject derived classes added to the NIB as suggested here.

Although I've done all of these steps in isolated cases, I've never taken it all the way to this sort of formal solution, but with some planning it should be fairly reliable and robust.

Community
  • 1
  • 1
Barney Mattox
  • 2,964
  • 1
  • 16
  • 11
0

Maybe i didnt understand u?
you have library in the Interface builder u can move every component u want and place it on your view. (u can add another view by adding UIView and change its class name in the 4th tab).
then u declare vars with IBOutlet and connect them from the 2nd tab of ur file's owners to their components...another question?

Ratinho
  • 298
  • 1
  • 6
  • Hmm.. Let's say I have 4 XIBs in my project - 2 "standard" View-Based Application template XIBs: MainWindows.xib and TestViewController.xib. Now to keep things clean I want to create 2 additional view's - every view in another XIB: CustomTextView.xib and CustomProgressView.xib. I add UILabel and UIButton to first and UILabel UIProgressView to the second one. Now I want to add those two custom views to my TestViewController.xib view. How do I do that (other than a way I did it and using XIB design not UIView subclass drawing everything in drawRect)? – shw Feb 02 '11 at 02:08
  • ok i think i got you.if CustomTextView and CustomProgressView are views or extends it, you should add UIView into ur main view - for exmaple mainWindow- and in the identity inspector (the 4th tab in the inspector) u should change Class from UIView to ur class(CustomProgressView e.g). – Ratinho Feb 02 '11 at 02:39
  • Ok - but for that I have to create a class which is a subclass of UIView - otherwise the CustomTextView won't be visible in the Class field. If I do so how do I "connect" it with the CustomTextView.xib file I created? I managed to override initWithCoder method, load that xib using `[NSBundle loadNibNamed]` method and add first view it returns as a subview of that UIView subclass but it still feels like hacking and like there should be a better way to do it. – shw Feb 02 '11 at 03:23
  • open your XIB in interface builder, click cmd+a,cmd+c,and create new normal view controller and paste it in its XIB ;) – Ratinho Feb 02 '11 at 12:11
  • 1
    heh - that's what I was trying to avoid to keep things organized and create re-useable views/controls not to keep everything in one nib. for now I created UIView subclass with methods that helps load XIB files and add them to that view and created subclass of that class, override initWithCoder where I use those methods to load and "connect" XIB. If that's the "only way" than Apple should fix that. I don't know why they can't just find and load XIB files to library from project the same way they do this for UIView subclasses. – shw Feb 02 '11 at 12:40
0

Unfortunately, you can't do what you want to do with UIKit. IB Plugins only work for OS X, and Apple explicitly doesn't allow them for use with iOS development. Something to do with them not being static libraries. Who knows, they may change this someday, but I wouldn't hold your breath.

quickthyme
  • 1,250
  • 1
  • 13
  • 16