我熟悉为我自己的UIView子类创建XIB的大部分过程,但并非所有内容都适合我 - 它主要与IBOutlets链接有关。我可以让他们以看似迂回的方式工作。
我的设置是:
我的init方法是我遇到问题的地方。
我尝试使用NSBundle mainBundle的'loadNibNamed'方法并将所有者设置为'self',希望我创建一个视图实例,它会自动将其出口与我班级中的出口相匹配(我知道怎么做,我很小心)。然后我想我想让'self'等于那个nib中索引0的子视图,而不是做
self = [super init];
或类似的东西。
我觉得我在这里做错了,但是在线示例在init方法中有类似的事情,但是他们将子视图0分配给view属性并将其添加为子项 - 但是那不是那么共有两个MyClass实例?一个基本上与IBOutlets无关,包含通过loadNibNamed实例化的子MyClass?或者充其量,它不是一个MyClass实例,带有一个额外的中间UIView,其中包含我最初想要的所有IBOutlets作为MyClass的直接子项吗?当涉及到像instanceOfMyClass.frame.size.width这样的事情时,这会引起一些轻微的烦恼,因为它返回0,当引入的子UIView返回我正在寻找的实际帧大小时。
我在做错的事情是我在init方法中搞乱了loadNibNamed吗?我应该做更像这样的事吗?
MyClass *instance = [[MyClass alloc] init];
[[NSBundle mainBundle] loadNibNamed:@"MyClass" owner:instance options:nil];
或者喜欢这个?
MyClass *instance = [[[NSBundle mainBundle] loadNibNamed:@"MyClass" owner:nil options:nil] objectAtIndex:0];
提前感谢您的任何帮助。
答案 0 :(得分:23)
第二个选项是正确的。您可以做的最具防御性的代码是这样的:
+ (id)loadNibNamed:(NSString *)nibName ofClass:(Class)objClass {
if (nibName && objClass) {
NSArray *objects = [[NSBundle mainBundle] loadNibNamed:nibName
owner:nil
options:nil];
for (id currentObject in objects ){
if ([currentObject isKindOfClass:objClass])
return currentObject;
}
}
return nil;
}
并且这样打电话:
MyClass *myClassInstance = [Utility loadNibNamed:@"the_nib_name"
ofClass:[MyClass class]];
// In my case, the code is in a Utility class, you should
// put it wherever it fits best
我假设您的MyClass是UIView
的子类?如果是这种情况,那么您需要确保.xib的UIView
实际上是MyClass类。在选择视图
答案 1 :(得分:7)
您需要做的就是通过loadNibNamed
创建子视图,设置框架,然后将其添加到子视图中。例如,我使用MyView
类添加了三个子视图,这是一个UIView
子类,其接口在NIB中定义,MyView.xib
:
因此,我为initWithFrame
子类定义UIView
:
- (id)initWithFrame:(CGRect)frame
{
NSLog(@"%s", __FUNCTION__);
self = [super initWithFrame:frame];
if (self)
{
NSArray *nibContents =
[[NSBundle mainBundle] loadNibNamed:@"MyView"
owner:self
options:nil];
[self addSubview:nibContents[0]];
}
return self;
}
因此,例如,在我的UIViewController
中,我可以加载一些这些子类UIView
对象,如下所示:
for (NSInteger i = 0; i < 3; i++)
{
CGRect frame = CGRectMake(0.0, i * 100.0 + 75.0, 320.0, 100.0);
MyView *myView = [[MyView alloc] initWithFrame:frame];
[self.view addSubview:myView];
// if you want, do something with it:
// Here I'm initializing a text field and label
myView.textField.text = [NSString stringWithFormat:@"MyView textfield #%d",
i + 1];
myView.label.text = [NSString stringWithFormat:@"MyView label #%d",
i + 1];
}
我最初建议使用控制器,我会在下面保留这个答案以供历史参考。
原始回答:
我在这里看不到任何对视图控制器的引用。通常你有一个UIViewController
的子类,然后用
MyClassViewController *controller =
[[MyClassViewController alloc] initWithNibName:@"MyClass"
bundle:nil];
// then you can do stuff like
//
// [self presentViewController:controller animated:YES completion:nil];
如果需要,NIB文件MyClass.xib
可以指定UIView
的基类,其中包含所有与视图相关的代码(例如,假设MyClass是{的子类{1}})。
答案 2 :(得分:2)
这是我使用的一种方法:
UIView
创建一个子类,这将被称为MyClass
ParentViewController
。MyClass
。MyClass
中声明的任何商店/行动都将是
通过从View(而不是File的所有者)单击拖动来连接。如果要将它们连接到ParentViewController
的变量,请从文件所有者单击并拖动。ParentViewController
中,您需要声明一个实例
MyClass
的变量。 ParentViewController.h
添加以下内容:
@class MyClass
@interface ParentViewController : UIViewController {
MyClass *myClass;
}
@property (strong, nonatomic) MyClass *myClass;
在您的实现中合成这个并在您的实现中添加以下内容
viewDidLoad
方法:
- (void)viewDidLoad {
[super viewDidLoad];
[[NSBundle mainBundle] loadNibNamed:@"MyClass" owner:self options:nil];
self.myClass.frame = CGRectMake(X,Y,W,H); //put your values in.
[self.view addSubview:self.myClass];
}