我的目标是,在自己的XIB中设置一个子类UIView
(让我们称之为infoView
),以便我可以在许多UIViewController
中显示它。
问题:
到目前为止,当我将UIView
添加到UIViewController
时,我总是必须创建UIViewController
文件的UIView
.xib文件的所有者才能加载查看类似于:
...
//this is inside the calling UIViewController's method
// InfoView *infoView is ivar and a subclass of UIView
infoView = nil;
NSArray *bundle = [[NSBundle mainBundle] loadNibNamed:@"InfoView"
owner:self options:nil];
for (id object in bundle) {
if ([object isKindOfClass:[InfoView class]])
infoView = (InfoView *)object;
}
[[self view] addSubview:infoView];
...
但是我想在许多不同的UIView
中使用相同的UIViewController
,所以我实际上不想要文件的所有者,除了类本身。在ThomasM's question中,他将UIView
本身设置为文件的所有者,但没有成功。
在答案中,我找到了将文件所有者设置为nil的解决方案。为此,我必须将Interface Builder对象库中的所有调用UIViewController
对象添加到InfoView.xib文件中,并将它们与infoView
个出口连接。
但这感觉不对。 所以我想在这里收集解决方案
将UIView
与xib文件封装在一起,以便在许多不同的视图控制器中使用它。你们是如何处理的?
请求任何帮助。
编辑:
infoView
类似于当用户按下其中一个视图控制器上的按钮时出现的叠加层。它不是View控制器的“主要”视图。它提供了有关其超级视图视图控制器视图的详细信息,之后将消失。我只用不同的内容填充infoView
,抛出所有的调用视图控制器。
答案 0 :(得分:3)
像Hollance answer指出我正在使用UINib
。
要使用它,请保留.xib文件所有者nil
,并将infoView的所有自定义内容放在InfoView类实现的initWithCoder:
方法中。如果您获得InfoView.xib
之类的话,这将被调用:
// here InfoView is the name of the .xib file
UINib *infoNib = [UINib nibWithNibName:@"InfoView" bundle:nil];
NSArray *topLevelObjects = [infoNib instantiateWithOwner:self options:nil];
QInfoView *infoView = [topLevelObjects objectAtIndex:0];
答案 1 :(得分:1)
因此,您希望从要在多个UIView
中使用的笔尖加载UIViewController
,并且您希望将其连接到每个视图控制器上的插座。这是对的吗?
然后使用UIViewController
属性创建一个FakeViewController
子类(让我们称之为IBOutlet
)。将FakeViewController
设置为笔尖的文件所有者,并将UIView
连接到其出口。
完成。
您只需要确保所有其他视图控制器也具有这些插座属性(尽管它们不需要是IBOutlets
),但是nib加载器实际上并未检查以确保该类传入owner
参数等于您在Interface Builder中指定的类名。所以你可以假装它。
哦,如果你是OS 4.0及更高版本,请使用UINib
加载nib文件。
答案 2 :(得分:1)
另一种方法是根据NSObject
创建自己的“控制器”来定义自己的生命周期(而不是标准的UIViewController
生命周期)。
例如:
<强> BaseSubview.h:强>
@interface BaseSubview : NSObject {
UIView* _view;
}
@property (nonatomic, retain) IBOutlet UIView* view;
- (void)myMethod;
@end
<强> BaseSubview.m:强>
#import "BaseSubview.h"
@implementation BaseSubview
@synthesize view = _view;
- (id)init
{
self = [super init];
if (self) {
// ...
}
return self;
}
- (void)dealloc
{
[_view removeFromSuperView];
[super dealloc];
}
- (void)myMethod
{
// view specific logic here
_view.backgroundColor = [UIColor redColor];
}
@end
<强> InfoView.h:强>
#import "BaseSubview"
@interface InfoView : BaseSubview {
UILabel* _labelInfo;
}
@property (nonatomic, retain) IBOutlet UILabel* labelInfo;
@end
<强> InfoView.m:强>
#import "InfoView.h"
@implementation InfoView
@synthesize labelInfo = _labelInfo;
- (id)init
{
self = [super init];
if (self) {
// ...
}
return self;
}
- (void)myMethod
{
// view specific logic here
_labelInfo.text = @"current time...";
[super myMethod];
}
@end
<强> InfoView.xib:强>
<强> HugeAndComplicatedViewController.h:强>
// ...
// among other var definitions
InfoView* _infoView;
// ...
HugeAndComplicatedViewController.m ,最有趣的部分:
// when you decide to show your view
// probably in loadView
_infoView = [[InfoView alloc] init];
[[NSBundle mainBundle] loadNibNamed:@"InfoView" owner:_infoView options:nil];
[self.view addSubview:_infoView.view];
// possibly perform specific logic
[_infoView myMethod];
// no need sub-view any more
// probably in dealloc
[_infoView release];
所以现在你有了自己的子视图,其逻辑和设计与“巨大而复杂”的视图控制器分开。它可以包含您当前项目所需的任何生命周期。
答案 3 :(得分:0)
infoView需要是一个子视图吗?
在viewController中:
-(id) init {
self = [super initWithNibName:@"myNib" bundle:nil];
if (self) {
// code here
}
}