Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom UIView Configured With InterfaceBuilder

Numerous people have asked a similar question, but the responses were either just vague enough or not in the direction I needed things to go, so I will attempt to ask this as concretely as possible. The context of this question is for iOS development using XCode 4.

I have an app where I use the same Widget numerous times. In this simple exercise the widget will be a fixed sized red box with a label at the top that the root view controller will change, but you can imagine it has lots of ImageViews and ScrollViews and looks pretty spiffy. This last point is key, because non-coding artistic designers want to be able to tweak this view globally without having to do the same thing over and over on each duplicated piece of the UI.

In the app I have replaced the ImageViews and ScrollViews that used to make up the widget with a single UIView, and using InterfaceBuilder set the Custom Class to Widget. I have outlets in the root view controller for these Widget objects properly hooked up. The Widget Class is a subclass of UIView, and the code is as follows:

@interface Widget : UIView {
    UILabel     *label;
}

@property (nonatomic, retain) IBOutlet  UILabel *label;
@property (nonatomic, copy) NSString *labelName;
@end


@implementation Widget
@synthesize label, labelName;

- (id)initWithCoder:(NSCoder *)aDecoder {
    if ((self = [super initWithCoder:aDecoder])) { 
        // This is the code that I want to disappear    
        CGRect pos = CGRectMake(5, 5, 90, 30);
        label = [[UILabel alloc] initWithFrame:pos];
        [self addSubview:label];
        self.backgroundColor = [UIColor redColor];
    }
    return self;
}

- (NSString *)labelName {
    return label.text;
}

// This live updates the label in this custom view
- (void)setLabelName:(NSString *)name {
    label.text = name;
}

- (void)dealloc {
    [super dealloc];
}
@end

The code works great, and I can live update the text in the custom views from the main view controller. However, the four lines of code that are in initWithCoder are the problem. Remember the designers? I have them at the point where they can work their magic with Interface Builder, but I can't for the life of me figure out how to get the UIView to load itself from a nib that they have designed. To manually try and replicate the positioning and properties of ever single item is not terribly exciting and pretty time-consuming (and yes I realize I would be done by now if I hadn't written this posting).

So very simply, how can I take an arbitrary .xib file and have it do the work I hand-rolled in initWithCoder? I am assuming it will be trivial at that point to hook up the IBOutlet for the UILabel, but please comment on this if I'm overly optimistic.

As a secondary question, once that is up and running on the real UI, I will have things like, UIScrollViews hooked up. Does Widget become the UIScrollViewDelegate or where does this code get parked. The root view controller should be oblivious to this, but it feels inappropriate to put code I traditionally put in a View Controller into a UIView object.

like image 682
Waldo Avatar asked Oct 11 '22 08:10

Waldo


1 Answers

Declare an IBOutlet (IBOutlet UIView *Widget;) in your controller. Put the Widget view(from the designer) in the xib of your controller(If your controller has no xib, then you can create or specify a new xib for your controller). Then hook up this view to the above IBOutlet. If you want to avoid the hooking of labels, scrollview etc.. whenever the designer makes changes, you have to replace the entire xib instead of just replacing the view.

like image 112
jjpp Avatar answered Dec 06 '22 04:12

jjpp