我知道这是非常直接的,但是经过太多的拉毛后,我无法解决问题.
我看过教程解释如何使用XIB和所有创建视图.但它们都没有解决我在这里的情况.
我有一个XIB文件,一个自定义的UIView子类,它有很少的标签和按钮.UIView子类是可重用的,这就是我不能在任何单个View控制器中安装插座的原因.因此,我将此视图的各个控件(子视图)存储在我的自定义UIView本身中.这是合乎逻辑的,因为没有视图控制器应该拥有此自定义视图的子视图,该视图将包含在每个视图控制器中.
问题是,我不知道如何完全初始化整个UI.
这是我的UIView子类的代码:
@interface MCPTGenericView : UIView +(id)createInstance : (bool) bPortrait; @property (weak, nonatomic) IBOutlet UIView *topView; @property (weak, nonatomic) IBOutlet UIView *titleView; @property (weak, nonatomic) IBOutlet UILabel *titleLabel; @property (weak, nonatomic) IBOutlet UIButton *logoButton; @property (weak, nonatomic) IBOutlet UITextField *searchTextField; @property (weak, nonatomic) IBOutlet UIButton *menuButton; @end
后来,我也计划将这个相同的XIB文件用于这个UIView的横向,我计划在同一个XIB中使用相同的上面的出口和横向控制.
以下是实施:
@implementation MCPTGenericView //@synthesize topView, titleLabel, titleView; +(id)createInstance : (bool) bPortrait { UIView * topLevelView = nil; MCPTGenericView * instance = [MCPTGenericView new]; NSArray * views = [[NSBundle mainBundle] loadNibNamed:@"MoceptGenericView" owner:instance options:nil]; int baseTag = (bPortrait)?PORTRAIT_VIEW_TAG_OFFSET:LANDSCAPE_VIEW_TAG_OFFSET; // make sure customView is not nil or the wrong class! for (UIView * view in views) { if (view.tag == baseTag) { topLevelView = view; break; } } instance.topView = (MCPTGenericView *)[topLevelView viewWithTag:baseTag + 1]; instance.searchTextField = (UITextField *)[topLevelView viewWithTag:baseTag + 2]; instance.menuButton = (UIButton *)[topLevelView viewWithTag:baseTag + 3]; instance.logoButton = (UIButton *)[topLevelView viewWithTag:baseTag + 4]; instance.titleView = [topLevelView viewWithTag:baseTag + 5]; instance.titleLabel = (UILabel *)[topLevelView viewWithTag:baseTag + 6]; return instance; } -(id)initWithCoder:(NSCoder *)aDecoder { if ((self = [super initWithCoder:aDecoder])) { [self addSubview:[[[NSBundle mainBundle] loadNibNamed:@"MCPTGenericView" owner:self options:nil] objectAtIndex:0]]; } return self; } -(void)awakeFromNib { [super awakeFromNib]; [self addSubview: self.titleView]; [self addSubview:self.topView]; } - (id) init { self = [super init]; if (self) { [[NSBundle mainBundle] loadNibNamed:@"MCPTGenericView" owner:self options:nil]; [self addSubview:self.topView]; [self addSubview:self.titleView]; } return self; } - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { // Initialization code [[NSBundle mainBundle] loadNibNamed:@"MCPTGenericView" owner:self options:nil]; [self addSubview:self.topView]; [self addSubview:self.titleView]; } return self; } /* // Only override drawRect: if you perform custom drawing. // An empty implementation adversely affects performance during animation. - (void)drawRect:(CGRect)rect { // Drawing code } */ @end
有效的东西:
我成功地initWithFrame:frame
从我的viewcontroller 调用了.这样,我可以看到所有控件都已正确初始化.但是,如果我已经绘制了XIB,为什么还要提供一个帧?不应该loadNibNamed处理帧设置和布局的东西,因为这是XIB的预期用途?
我也对loadNibNamed需要一个所有者对象的方式感到困惑.为什么我们已经需要一个对象来从XIB获取相同的对象?那也是一个半生不熟的?
请帮忙...
令我感到困惑的是loadnibnamed
丢失xib布局和插座信息的方式.我终于找到了实现它的方法.
以下是有效的概述:
1)假设MyCustomView是您的自定义视图类 - 您将其及其子视图设计为XIB的一部分.您可以通过界面构建器执行此操作,因此不言自明.
2)通过Xcode - > File - > New - > Objective C Class添加MyCustomView.h和MyCustomView.m(样板).
3)接下来,在MyCustomView.xib中,设置File的Owner = MyCustomView(刚刚添加的类名).不要触摸最顶级View的自定义类 - 将其保留为UIView.否则它将最终递归!
4)在MyCustomView.h中,创建与MyCustomView.xib中的子视图对应的几个出口.
如:
@property (weak) IBOutlet UILabel * label1; @property (weak) IBOutlet UIButton * button1;
5)转到MyCustomView.xib.选择每个子视图(标签,按钮),右键单击,从"新建引用插座"拖动并将其向上拖动到文件所有者.
这将弹出一个与您拖动的子视图类型匹配的出口列表.如果从标签拖动,它将弹出label1,依此类推.这表明您在此步骤中所做的一切都是正确的.
另一方面,如果您在任何步骤中搞砸了,则不会出现弹出窗口.检查步骤,尤其是3和4.
如果您没有正确执行此步骤,Xcode将欢迎您将遵循以下异常:
setValue:forUndefinedKey: this class is not key value coding-compliant for the key
6)在MyCustomView.m中,粘贴/覆盖以下代码:
-(id)initWithCoder:(NSCoder *)aDecoder { self = [super initWithCoder:aDecoder]; if (self) { NSString * nibName = @"MyCustomView"; [[[NSBundle mainBundle] loadNibNamed:nibName owner:self options:nil] firstObject]; [self addSubview:self.labelContinentName]; } return self; }
此步骤至关重要 - 它将您的出口值(label1,button1)从零设置为有形子视图,最重要的是,根据您在MyCustomView.xib中设置的内容设置其框架.
7)在storyboard文件中,添加MyCustomView类型的视图 - 就像任何其他视图一样:
在View Controller主视图矩形中拖动UIView
选择新添加的视图
在Utilities - > Identity Inspector中,设置自定义类值= MyCustomView.
它应该是运行没有问题!