Question

I have a view called FeedView, handled by FeedViewController.

I also have a XIB called "NearestStore" which is handled by a view controller named "NearestStoreViewController". NearestStore xib has labels, buttons, etc. In the view controller I have outlets that are connected to the subviews in NearestStore.xib.

NearestStore inherits from UIButton (so it's easier to handle click event).

On FeedViewController.xib I have a UIButton that has been set to be of type NearestStore.

So far so good. This is on my FeedViewController:

__weak IBOutlet NearestStoreButton *btn_nearestStore;

The outlet is connected on the xib to the outlet.

NearestStoreViewController has several outlets to subviews like:

@property (nonatomic, weak) IBOutlet  UILabel *lbl_distance; 
@property (nonatomic, weak) IBOutlet  UIImageView *img_distance;

For some reason, on my FeedViewController the reference to btn_nearestStore is fine, but all the subviews are nil.

For example:

btn_nearestStore.lbl_distance 

is nil

What am I missing?

Was it helpful?

Solution

This sounds exactly as the system is supposed to work. It is not easy to create a custom widget using xibs.

Here's how it works:

Your FeedViewController will preform xib loading for the corresponding FeedView. During this load, it notices the NearestStoreButton subview. As a consequence, it creates such a view using the - (id)initWithCoder: message on the NearestStoreButton class. It will not magically notice the corresponding .xib nor the corresponding viewController.

If you need to use a xib within a xib, you need to do the loading manually for all subviews. Keep in mind that you somehow need to create/use the appropriate owners (view controllers) for these secondary xibs.

OTHER TIPS

It's hard to tell from your description, but this sounds like a problem with "owner" of the loaded NearestStoreButton XIB. When you load a NIB, you give the loader an owner, and its this owner on which most outlet bindings and actions are made. If you're loading your NearestStoreButton with UINib, then when you call instantiateWithOwner:options:, make sure you pass the object on which the outlets should be set as the owner.

When are you calling the outlet? If you are trying to access the property in the initWithCoder method of the view, it's not guaranteed that object has been instantiated.

If you access your property in the awakeFromNib method within the view you should be able to get it. For instance, I have a custom view, and my code looks as such:

- (id)initWithCoder:(NSCoder *)aDecoder
{
    self = [super initWithCoder:aDecoder];
    if (self) {
        //Don't style the subviews in here since they won't be initialized
    }
    return self;
}

- (void)awakeFromNib
{
    [super awakeFromNib];
    [self styleViews];
}

- (void)styleViews
{
     //access my properties and style them in here
}

Following post contains detailed explanation about creating custom views using Nib:

creating custom view using Nib

After I create the customInit as mentioned in the post, I am able to get the IBOutlets allocated.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top