2013-03-19 61 views
2

我已经在这里看到了几个答案,似乎得到了我后,但我不能让他们任何工作。如何将UIView XIB“导入”UIViewController XIB?

MyView是UIView子类使用图像和布局,并在MyView.xib的风格,并在MyView.(h|m)势必IBOutlets文本字段屈指可数。 File's Owner未在XIB中设置,但MyView是顶级对象的类。在运行时,我通过NSBundle'sloadNibNamed动态加载各种MyView到某些视图控制器。一切都顺其自然。

但我有另一个视图控制器,MyVC,在设计时我想用MyView的几个实例来填充。根据直觉,我在MyVC.xib中放置了一个UIView对象,其大小与MyView相同,将其类型设置为MyView,在MyVC.h中添加了IBOutlet声明,并连接了该连接。

当我运行时,MyVC显示没有MyView。但是,调试表明已建立连接,视图确实是MyView,并且MyView'sawakeFromNib确实执行。我确信MyVC'sMyView位于层次结构的顶部,因为我将它的背景设置为鲜艳的红色。那么魔鬼在哪里MyView

+1

的意见是'awakeFromNib''d,但将有称为其'-initWithCoder' init方法,从视图控制器XIB而非MyView.xib的数据。如果这是有道理的... – 2013-03-19 20:14:08

回答

1

最简单的解决方案是,更换旧视图使MyView有一个子视图,它是其后代视图的其余部分的容器。这使您可以在MyVC.xibMyView.xib中的内容之间建立单点联系,并可让您在两个xib中连接插座。

MyVC.xib中,将每个占位符视图的类别设置为MyView

MyView.xib中,将顶级视图的类别设置为UIView。将文件所有者的类别设置为MyView。如果您在MyView.xib中连接的MyView上有任何网点,您将需要将它们重新连接到文件所有者,因为顶级视图不再具有这些网点。

-[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.xibMyView.xib连接其他对象的网点的MyView实例。但是,您无法将MyVC.xib中的其他对象的插座连接到MyView.xib中的其他对象,反之亦然。

+0

我不确定我对此做过什么,但你的答案看起来不错。 – QED 2016-06-01 15:06:56

0

ORIGINAL:覆盖的initWithCoder,一个糟糕的主意,因为下面的评论说

新建议:

  • 使用你的技术现在创建MyVC视图(MyView的情况下,将基本上是空的观点)

然后在MyVC的viewDidLoad:方法:

  • 创建使用你的笔尖,每一个的那些在MyView的

  • 替换每个空的(即占位符)MyViews与您刚刚创建的那些,确保帧被适当地设置新的MyView的情况下(设置任何属性/实例变量,并且使用“ - (无效)exchangeSubviewAtIndex:(NSInteger的)索引1 withSubviewAtIndex:(NSInteger的)索引2”与子视图阵列中的新的)

+0

这并不是简单的工作。当你加载笔尖时,它也会*使用'initWithCoder:'。您必须采取预防措施以避免无限递归。 – 2013-03-20 17:40:41

+0

@robmayoff猜你会发现当你与大自然搞混时会发生什么?让我再尝试一次。 – 2013-03-20 18:48:23