无法在以编程方式加载的XIB中访问和设置UILabel文本

时间:2013-12-09 01:54:59

标签: ios uiscrollview xib uipagecontrol

这是我第一次在StackOverflow上发帖 - 我已经把这头发拉了太久了。希望这里的社区可以提供帮助。

我已经设置了一个UIScrollView / PageControl来翻阅4页。我试图将.xib加载到ScrollView中4次,每次都使用不同的文本和图像。

不幸的是,我能够加载xib,但无法更改文本/图像,我不知道为什么。我认为这可能与我无法在ViewController中访问已加载的NIB的UILabel有关。

这是CardView.xib(CardView.h)的.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

这是CardView.m文件:

#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

我将xib的UIImageView和UILabel出口连接到CardView.h。

现在在我的ViewController中,我将xib添加到我的scrollView中4次:

@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);
}

我不确定为什么subview.cardLabel.text实际上没有更改文本。似乎subview.cardLabel是nil,但我清楚地看到UILabel带有我在iOS模拟器运行时在xib中的默认文本。

3 个答案:

答案 0 :(得分:0)

好的,假设您已经在界面构建器中创建了xib并链接了IBOutlets,我认为这些行在initWithFrame中

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

实际上是在视图的顶部创建一个视图,所以尽管您正在更改界面中创建的标签,但由于重复的视图已经分层,所以您无法看到更改。尝试取出我上面引用的行。

编辑:另外,就像Phillip指出的那样,为什么CardView.h会说“BMTutorialCardView”,为什么在.m和文件名中的其他内容都说“CardView”时用“BMTutorialCardView”xib初始化视图?你有两个独立的课程吗?实际上,我看你的代码越多,我对你要做的事情就越感到困惑......

答案 1 :(得分:0)

替换这两行:

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

有了这个:

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

我不认为这是最好的解决方案,但它应该适用于您的情况而不必改变太多。

......正如其他人已经说过的那样,您需要检查您的班级名称(BMTutorialCardView vs CardView)。

修改

我想我更喜欢this approach。确保将nib文件中的文件所有者更改为UIViewController,并将其view出口连接到CardView(或者调用UIView子类的任何内容)。

然后,您可以删除完全不在initWithFrame:方法中的代码,并在viewDidLoad中替换此行:

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

有了这个:

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

答案 2 :(得分:0)

问题大致可以是View Life Cycle。让我们说,我们有单独的视图插图Beer.xibBeer.class(其中.xib中的视图中的子视图存储在类实现中作为@IBOutlets)。最后,我们有BeerInfoViewController.swift(由UIViewController继承)。首先,我们需要将.xib加载到我们的BeerInfoViewController(我很抱歉Swift,我太小了Objective-C}:

override func viewDidLoad() {
    super.viewDidLoad()
    guard let beerXib = Bundle.main.loadNibNamed("Beer", owner: self, options: nil)?.first as? BeerInfoViewController else {
        fatalError("Beer.xib is not found. ❌")
    }
    beerXib.frame = CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height)
    self.view.addSubView(beerXib)
}

好的,Beer.xib已加载到BeerInfoViewController的根视图中。接下来,您需要访问位于@IBOutlets的{​​{1}}。 不再说

Beer.class

糟糕。不要忘记在故事板中明确为您beerXib.subviews.forEach { subView in // Do whatever you want to do with subviews! } 定义一个类!您必须在Identity Inspector中执行此操作,或者在Xcode中默认键入 .xib + cmd + option