Search code examples
iosuiscrollviewxibuipagecontrol

Can't access and set Text of UILabel in a programmatically loaded XIB


This is my first time posting on StackOverflow - been pulling my hair out on this one for too long. Hoping the community here can help.

I've setup a UIScrollView/PageControl to page through 4 pages. I'm trying to load a .xib into the ScrollView 4 times, each time with a different text and image.

Unfortunately, I'm able to load the xib, but not able to change the text/image, I'm not sure why. I think it might have something to do with not being able to access the UILabel of the loaded NIB in my ViewController.

Here's the .h file of the CardView.xib (CardView.h):

#import <UIKit/UIKit.h>

@interface BMTutorialCardView : UIView

@property (strong, nonatomic) IBOutlet UIView *contentView;
@property (weak, nonatomic) IBOutlet UIImageView *cardImage;
@property (weak, nonatomic) IBOutlet UILabel *cardLabel;

@end

And here's the CardView.m file:

#import "CardView.h"

@implementation CardView

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
        UIView *xibView = [[[NSBundle mainBundle] loadNibNamed:@"BMTutorialCardView" owner:self options:nil] objectAtIndex:0];
        [self addSubview:xibView];
    }
    return self;
}
@end

I hooked up both the UIImageView and UILabel outlets from the xib to CardView.h.

Now in my ViewController, I add the xib 4 times into my scrollView:

@implementation BMViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    for (int i = 0; i < 4; i++) {
        CGRect frame;
        frame.origin.x = self.scrollView.frame.size.width * i;
        frame.origin.y = 0;
        frame.size = self.scrollView.frame.size;

        CardView *subview = [[BMTutorialCardView alloc] initWithFrame:frame];

        //The following line doesn't change the text.
        subview.cardLabel.text = @"This line doesn't change the text on the label";
        [self.scrollView addSubview:subview];
    }

    self.scrollView.contentSize = CGSizeMake(self.scrollView.frame.size.width * 4, self.scrollView.frame.size.height);
}

I'm not sure why subview.cardLabel.text doesn't actually change the text. It seems like subview.cardLabel is nil, but I clearly see the UILabel with the default text that I had in the xib when iOS simulator is run.


Solution

  • Replace these 2 lines:

    UIView *xibView = [[[NSBundle mainBundle] loadNibNamed:@"BMTutorialCardView" owner:self options:nil] objectAtIndex:0];
    [self addSubview:xibView];
    

    With this:

    self = [[[NSBundle mainBundle] loadNibNamed:@"CardView" owner:self options:nil] objectAtIndex:0];
    self.frame = frame;
    

    I don't think it's the best solution, but it should work in your situation without having to change too much.

    ...and as the others have already said, you need to check your class names (BMTutorialCardView vs CardView).

    EDIT:

    I think I prefer this approach. Make sure you change the File's Owner in your nib file to UIViewController and hook up its view outlet to your CardView (or whatever your UIView subclass is called).

    Then you can remove the code that's not working in your initWithFrame: method altogether, and replace this line in your viewDidLoad:

    CardView *subview = [[BMTutorialCardView alloc] initWithFrame:frame];
    

    With this:

    UIViewController *controller = [[UIViewController alloc] initWithNibName:@"CardView" bundle:nil];
    CardView *subview = (CardView *)controller.view;
    subview.frame = frame;