【问题标题】:UIView created through Interface Builder has no subviews in viewDidLoad通过 Interface Builder 创建的 UIView 在 vi​​ewDidLoad 中没有子视图
【发布时间】:2015-01-24 17:20:49
【问题描述】:

上下文:

  • MainView.xib:我已经布置了我的 UI 元素,并煞费苦心地使用自动布局将它们完美对齐。有一大堆 UIButtons、一个 UILabel 和一个 UIToolbar。层次结构非常平坦,如下所示:

    UIView // Hooked up to ViewController
    |
    - UILabel
    - UIButton
    - UIButton
    - UIButton
    - ... // more buttons
    - UIToolbar
    
  • ViewController.m:

    #import "ViewController.h"
    
    @interface ViewController ()
    
    @property NSArray *_allButtons;
    
    // Interface elements
    @property IBOutlet UILabel *titleLabel;
    @property IBOutlet UIButton *button1;
    @property IBOutlet UIButton *button2;
    // ... lots more buttons
    @property IBOutlet UIToolbar *toolbar;
    
    @end
    
    @implementation ViewController
    
    - (void)loadView {
        UIView *mainView = [[[NSBundle mainBundle] loadNibNamed:@"MainView"
                                                          owner:self
                                                        options:nil] objectAtIndex:0];
        self.view = mainView;
    }
    
    - (void)viewDidLoad {
        [super viewDidLoad];
    
        // BREAK_POINT
    
        // ... code to wire up the UIButtons to dynamically created objects
    }
    

奇怪的观察:

我已经正确地将我单独创建的 IBOutlet UIButton button<n> 指针连接到 .xib 文件中的 UIButtons。该代码运行良好。

但是,像这样单独维护所有按钮很痛苦。我可以通过编程方式创建它们,但在 Interface Builder 中以可视方式移动它们会更好(现在我已经学会了如何使用它)。

我想我可以删除 UIButtons 的 IBOutlet 连接,并在 MainView.xib 中找到它们作为主 UIView 的子视图,在 viewDidLoad 中有一些类似这样的代码:

for (UIView *view in self.view.subviews) {
    if( [view isKindOfClass:[UIButton class]]) {
        [self._allButtons addObject:view];
    }
}

不幸的是,self._allButtons 原来是一个空数组。

所以,我带回了 IBOutlet 连接,在viewDidLoad 的断点处下降,然后看到了这个:

(lldb) po self.view
<UIView: 0x7fa7897e2140; frame = (0 0; 600 600); autoresize = W+H; layer = <CALayer: 0x7fa7897e2210>>

(lldb) po self.view.subviews
<__NSArrayI 0x7fa789713500>(

)
(lldb) po [self.view.subviews count];
 nil
(lldb) po self.button1
<UIButton: 0x7fa78955ea70; frame = (-23 -15; 46 30); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x7fa7897663d0>>

这非常奇怪...button1 已初始化,但不是 UIView 的子视图。

问题:

1。为什么viewDidLoad 中的self.view.subviews 为空?

2。有没有办法可以在 Interface Builder 中创建 UIButton 并在 viewDidLoad 中获取对它们的引用?

【问题讨论】:

    标签: ios objective-c iphone uibutton interface-builder


    【解决方案1】:

    尝试在

    中做到这一点
    - (void)viewDidLayoutSubviews{
    
    
    }
    

    加载所有子视图后调用此方法。希望这会对你有所帮助:)

    【讨论】:

    【解决方案2】:

    所以我自己想出了一大堆,使用一些旧的 Apple 文档。这真的有点普通。我将把问题 #1 移到一个单独的问题,开销更少,因为看起来没有人会费心阅读这个巨大的问题。

    不为UIButtons 的集合制造大量IBOutlets 的最简单方法是……等待它……使用IBOutletCollection

    @property IBOutletCollection(UIButton) NSArray *buttons;
    

    然后将 UIButtons 拖放到 xib 中的 File Owner 的 IBOutletCollection 中。我的代码更干净了,而且我不必在子视图等之间循环遍历。

    来源:

    View Programming Guide for iOS - Locating Views in a View Hierarchy:

    存储对相关视图的引用是定位视图的最常用方法,并且可以非常方便地访问这些视图。如果您使用 Interface Builder 创建视图,则可以使用 outlet 将 nib 文件中的对象(包括表示管理控制器对象的 File's Owner 对象)相互连接。对于您以编程方式创建的视图,您可以将这些视图的引用存储在私有成员变量中。

    看起来访问在 Interface Builder 中创建的元素的唯一方法是通过 IBOutlets/IBOutletCollections。

    稍后将使用指向我的新问题的链接编辑此答案。

    问题 #1 移至此处:Why is self.view.subviews an empty array in viewDidLoad?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-08-15
      • 2013-08-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多