如何将 UIView XIB“导入”到 UIViewController XIB?
Posted
技术标签:
【中文标题】如何将 UIView XIB“导入”到 UIViewController XIB?【英文标题】:How to "import" a UIView XIB into a UIViewController XIB? 【发布时间】:2013-03-19 20:06:14 【问题描述】:我在这里看到了一些似乎符合我所追求的答案,但我无法让它们中的任何一个起作用。
MyView
是一个 UIView 子类,其中有一些图像和文本字段在MyView.xib
中布局和样式,并绑定到MyView.(h|m)
中的 IBOutlets。 File's Owner
在XIB中没有设置,但是MyView是顶层对象的类。在运行时,我通过NSBundle's
loadNibNamed
将各种 MyViews 动态加载到某些视图控制器中。一切都很顺利。
但我有另一个视图控制器MyVC
,在设计时我想填充几个 MyView 实例。凭直觉,我在MyVC.xib
中布局了一个与MyView大小相同的UIView对象,将其类型设置为MyView
,在MyVC.h
中添加了IBOutlet声明,并连接了连接。
当我运行时,MyVC
显示没有 MyView
。但是调试表明连接已经建立,视图确实是MyView
,而MyView's
awakeFromNib
确实执行了。而且我确信MyVC's
MyView
在层次结构的顶部,因为我将它的背景设置为漂亮的鲜红色。那么MyView
哪里有鬼?
【问题讨论】:
视图是awakeFromNib
'd,但将调用它们的-initWithCoder
init 方法,数据来自视图控制器xib而不是MyView.xib。如果这是有道理的......
【参考方案1】:
最简单的解决方案是让MyView
有一个子视图,它是其余子视图的容器。这为您提供了 MyVC.xib
和 MyView.xib
中的内容之间的单点联系,并允许您连接两个 xib 中的插座。
在MyVC.xib
中,将每个占位符视图的类设置为MyView
。
在MyView.xib
中,设置顶层视图的类为UIView
。将文件所有者的类设置为MyView
。如果您在MyView
上有任何在MyView.xib
中连接的插座,您需要将它们重新连接到文件的所有者,因为***视图不再有这些插座。
在-[MyView initWithCoder:]
中,加载MyView.xib
并将其***视图添加为您的子视图。未经测试的示例:
+ (UINib *)nib
static dispatch_once_t once;
static UINib *nib;
dispatch_once(&once, ^
nib = [UINib nibWithNibName:NSStringFromClass(self) bundle:[NSBundle bundleForClass:self]];
);
return nib;
- (id)initWithCoder:(NSCoder *)aDecoder
if (self = [super initWithCoder:aDecoder])
NSArray *contents = [[self.class nib] instantiateWithOwner:self options:nil][0];
UIView *containerView = contents[0];
// Make sure the container view's size tracks my size.
containerView.frame = self.bounds;
containerView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
self.autoresizesSubviews = YES;
if ([self respondsToSelector:@selector(setTranslatesAutoresizingMaskIntoConstraints:)])
self.translatesAutoresizingMaskIntoConstraints = YES;
containerView.translatesAutoresizingMaskIntoConstraints = YES;
// If you're using autolayout in both xibs, you should probably create
// constraints between self and containerView here.
[self addSubview:containerView];
return self;
这样就可以将MyView
的出口连接到MyVC.xib
中的事物和MyView.xib
中的事物,并且可以将MyVC.xib
和MyView.xib
中的其他对象的出口连接到MyView
的实例。但是,您不能将MyVC.xib
中的其他对象的出口连接到MyView.xib
中的其他对象,反之亦然。
【讨论】:
我不确定我对此做了什么,但你的答案看起来不错。【参考方案2】:ORIGINAL:重写 initWithCoder,正如下面的评论所说的那样是个坏主意
新建议:
使用您现在拥有的技术创建 MyVC 视图(MyView 实例基本上是空视图)然后在MyVC的viewDidLoad:方法中:
使用您的 nib 创建新的 MyView 实例,为 MyView 中的每个实例创建一个
将每个空的(即占位符)MyViews 替换为您刚刚创建的那些,确保正确设置框架(设置任何属性/ivars,并使用 '- (void)exchangeSubviewAtIndex:(NSInteger)index1 withSubviewAtIndex:(NSInteger)index2' 用子视图数组中的新视图替换旧视图)
【讨论】:
这不是简单的工作。当您加载笔尖时,它也使用initWithCoder:
。您必须采取预防措施以避免无限递归。
@robmayoff 猜猜这就是当你和大自然鬼混时会发生的事情!让我再试一次。以上是关于如何将 UIView XIB“导入”到 UIViewController XIB?的主要内容,如果未能解决你的问题,请参考以下文章
如何将 UITableView 作为子视图添加到 xib 中的 UIView?
如何将额外参数传递给链接到 XIB 文件的自定义 UIView?