0

I followed the tutorial outlined here to load a custom xib in my view controller.

The class of the xib inherits from UIView but also needs a property view:

 @interface MYBannerView : UIView
 @property (nonatomic, weak) IBOutlet UIView *view;
 @end  

I find it strange that it needs this, as its like having a view within a view which seems redundant. Is there any particular reason for this?

Edit

I followed this tutorial here which outlines this:

http://www.maytro.com/2014/04/27/building-reusable-views-with-interface-builder-and-auto-layout.html

user1686342
  • 1,265
  • 1
  • 18
  • 24
  • theoretically you don't need the property, you can use self... – francesco.venica Nov 05 '15 at 19:20
  • 2
    why would it need that? where did you read that? – André Slotta Nov 05 '15 at 19:21
  • I added the original link i used as the tutorial – user1686342 Nov 05 '15 at 19:25
  • The specific answer is given below. But really if you're learning iOS you should be using CONTAINER VIEWS for anything at all like this. Everything is now container views. They are absolutely trivial to use - it was a spectacular advance in programming efficiency by Apple. [Long tutorial](http://stackoverflow.com/a/23403979/294884) – Fattie Nov 05 '15 at 22:20
  • Regarding the specific question, I would really urge you to ignore the particular tutorial you link to. If - for some reason - you want to do that. (Or, if you are reading this using a time machine from 1990 when simple container views did not exist :) ) ... just do this http://stackoverflow.com/a/21073901/294884 More info on the same topic ... http://stackoverflow.com/a/25910881/294884 – Fattie Nov 05 '15 at 22:22
  • This is also helpful .. http://stackoverflow.com/a/15379141/294884 .. but again there is utterly no reason you would do this today. Just use a container view. Totally easy. – Fattie Nov 05 '15 at 22:23

2 Answers2

0

No, your UIView subclass doesn't need an outlet to the view to be functional. In fact, using self you have access to the view itself. What about tutorial: when author added view A (let's call it so) on MYViewController's view, he set view A class to be MYBannerView. Running app won't show anything because MYBannerView xib wasn't loaded and didn't replaced content from view A. So author loads this xib in initWithCoder, set outlet using value returned by loadNibNamed: and adds view loaded from MYBannerView to view A. The process is a little bit messy but it works.

nsinvocation
  • 7,559
  • 3
  • 41
  • 46
0

The author of that tutorial is using the view outlet to load the view from the xib when MYBannerView is initialized programatically

- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
    self = [super initWithCoder:aDecoder];
    if (self) {
        NSString *className = NSStringFromClass([self class]);
        self.view = [[[NSBundle mainBundle] loadNibNamed:className owner:self options:nil] firstObject];
        [self addSubview:self.view];
        return self;
    }
    return nil;
}

Anything created in Interface Builder will not be loaded with a programatic init. loadNibNamed loads the UI from the xib.

If you want to override initWithFrame: to load the UI elements from the xib, your init method would look something like this:

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame]; // initialize your objects

    if (self) {
        [[NSBundle mainBundle] loadNibNamed:NSStringFromClass([self class]) owner:self options:nil]; // load your view from IB
    }

    return self; // return the view with all of the IB UI loaded
}
JAL
  • 41,701
  • 23
  • 172
  • 300
  • Still not 100% clear. As I understand, when a XIB is loaded programmatically, the initWithFrame is called and initWithCoder is only called when a UIView is set with the relevant class in the IB. What I'm trying to get at is: would it be possible to create a XIB, add UI components with IB to the Files Owner and then initialise programmatically using initWithFrame. – user1686342 Nov 05 '15 at 20:51
  • In order to initialize any UIView object created with interface builder, you must call `loadNibNamed:` in order to load the views from the xib. I edited my post to show an example with `initWithFrame:` – JAL Nov 05 '15 at 22:17
  • Thanks for the advice so far. So just to clarify, if I was to add some buttons and labels on the XIB via IB and then loaded the IB programmatically (which would call initWithFrame) then those labels and buttons wouldn't load? – user1686342 Nov 07 '15 at 21:07
  • Not quite. If you call any of the `init` methods programmatically (`init:`, `initWithCoder:`, `initWithFrame:`), the interface builder views will not load unless you override the initializer to call `loadNibNamed:`. – JAL Nov 08 '15 at 17:38
  • You can read more about this behavior in this question: http://stackoverflow.com/q/21722805/2415822 – JAL Nov 08 '15 at 17:42