【问题标题】:Loading custom UIView from nib, all subviews contained in nib are nil?从nib加载自定义UIView,nib中包含的所有子视图都是nil?
【发布时间】:2011-11-27 03:12:24
【问题描述】:

我有一个自定义的UIView 对象和一个定义视图/子视图布局的nib。我的插座已连接,当我从initWithFrame: 初始化对象时,一切正常。

我遇到的问题是当我使用 IB 将 UIView 嵌入另一个笔尖时;自定义 UIView 出现,但它包含的子视图都没有出现 - 实际上它们的符号都解析为 nil。我有一个非常小的 initWithCoder:awakeFromNib: 实现(只是做日志记录),我的理解是,当 nib 被反序列化时,子视图至少应该在这个过程中被初始化?

我自己得出的唯一结论是发生了以下两种情况之一:要么我的插座引用损坏/坏并且无法正常工作,要么我对从 nib 加载过程的理解有误,并且我错过了一些东西。

提前致谢!

编辑:(按要求为 Nekto 发布的代码...如您所见,它会记录日志,仅此而已,呵呵。)

- (id)initWithCoder:(NSCoder *)aDecoder {
    if ((self = [super initWithCoder:aDecoder])) {
        NSLog(@"ThumbnailGridView.initWithCoder frame= %f, %f", self.frame.size.width, self.frame.size.height);
    }
    return self;
}

- (void)awakeFromNib
{
    NSLog(@"ThumbnailGridView:awakeFromNib");
}

编辑 2:笔尖、控制器、子视图等

笔尖:我有一个包含 UIView 的笔尖。此 UIView 包含单个 UIScrollView,其中填充了在另一个 nib 中定义的 UIView 网格。 (注意:这部分工作正常,因为填充是通过编程完成的,并且与 initWithFrame: 调用一起使用。)这里的问题是 UIScrollView 符号在 initWithCoder: 和 awakeFromNib: 都被调用之后为 nil,所以对象只是被添加到零,没有任何反应。如果滚动视图符号不为零,我相信这会起作用。

控制器:有两个控制器使用它,一个是使用 initWithFrame: 完成的,并且可以完美运行,另一个将它嵌入为基于 nib 的引用。 (正如这里其他地方提到的,在 IB 中定义一个 UIView,设置自定义类。)我单步执行了代码,并且该视图 - 正在正确初始化 - 只有它的子视图“丢失”。

这是否有助于更清楚地了解情况?

【问题讨论】:

  • 只有在您发布一些代码的情况下,我们才能为您提供帮助。您可以从创建自定义子视图的位置开始,initWithFrame: 等。
  • 我应该注意,我的自定义子视图实际上只是在 IB nib 中为管理它的视图控制器定义的。 (设置一个 UIView 的位置,改变它的自定义类等等)
  • 我认为问题不在于您的 Objective C 代码(除了缺少对 [super awakeFromNib] 的调用)。我们需要知道您的项目中有哪些 nib 文件,每个 nib 中定义了哪些视图控制器和视图,以及您如何将自定义视图“嵌入”到另一个 nib 中。

标签: iphone ios uiview interface-builder nib


【解决方案1】:

您可能误解了 nib 加载的工作原理。如果您定义自定义 UIView 并创建一个 nib 文件来布置其子视图,您不能只是将 UIView 添加到另一个 nib 文件,将 IB 中的类名更改为您的自定义类并期望 nib 加载系统能够解决它。您需要修改自定义 UIView 类的 initWithCoder 以编程方式加载定义其子视图布局的 nib。例如:

- (id)initWithCoder:(NSCoder *)aDecoder {
    if (self = [super initWithCoder:aDecoder]) {
        [[NSBundle mainBundle] loadNibNamed:@"CustomView" owner:self options:nil];
        [self addSubview:self.toplevelSubView];
    }
    return self;
}

您的自定义视图的 nib 文件需要将“文件所有者”类设置为您的自定义视图类,并且您需要在自定义类中有一个名为“toplevelSubView”的插座连接到自定义视图 nib 文件中的视图作为所有子视图的容器。向您的视图类添加额外的出口并将子视图连接到“文件所有者”(您的自定义 UIView)。

或者,只需以编程方式创建自定义视图并绕过 IB。

【讨论】:

  • 感谢 Robin,这完全消除了我的不确定性和问题;我曾认为对 mainBundle 的调用是隐式的,并且在我的 initWithFrame: 方法中明确地进行了调用。这解决了一切,再次感谢!
  • 但这在某种程度上是连线的。我的意思是当我在 xib 中设置子视图标签号并加载 Nib 时,我可以通过调用例如访问子视图[单元格 viewWithTag:]。幸运的是,有一种方法可以检索属性并以编程方式访问它们,但如果它们不是呢?当它们更紧密地连接到任何属性或 ivars 时,是否还有一种方法可以以某种方式访问​​视图?
  • 我希望我的所有出口都在视图子类中 + 我想以编程方式从它们的 xib 加载这些子视图。我遵循了上述方法,但我不知道如何在视图控制器中初始化视图而不将它们放在情节提要中。来自 viewcontroller 的 loadNIBNamed 导致使用上述递归...该怎么办?
  • @JonRamvi 如何修复无限循环?
【解决方案2】:

检查您是否在每个被覆盖的方法中调用了 initWithCoder: 和 awakeFromNib 的“超级”实现,即

- (id)initWithCoder:(NSCoder *)decoder {
    if ((self = [super initWithCoder:decoder])) {
      ...your init code...
    }
    return self;
}

- (void)awakeFromNib {
     [super awakeFromNib];
     ...your init code...
}

【讨论】:

  • 设法忘记了[super awakefromNib];调用虽然添加它仍然没有给我对对象的有效引用。我仍然担心我错误地假设笔尖中定义的子视图是自动创建的......尽管这个概念有点违反直觉,因为那里有插座。
猜你喜欢
  • 2012-10-13
  • 1970-01-01
  • 2013-10-08
  • 1970-01-01
  • 1970-01-01
  • 2011-02-15
  • 1970-01-01
  • 1970-01-01
  • 2011-02-08
相关资源
最近更新 更多