Iphone 最佳实践:将子类UIView(具有自己的xib)作为UIViewController的子视图

Iphone 最佳实践:将子类UIView(具有自己的xib)作为UIViewController的子视图,iphone,ios,uiview,uiviewcontroller,interface-builder,Iphone,Ios,Uiview,Uiviewcontroller,Interface Builder,我的目标是,在自己的XIB中设计一个子类UIView(我们称之为infoView),这样我就可以在许多UIViewController中展示它 问题是: 到目前为止,当我将UIView添加到UIViewController时,我始终必须使UIViewController成为UIView的.xib文件的所有者,以加载视图,例如: ... //this is inside the calling UIViewController's method // InfoView *infoView is i

我的目标是,在自己的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]; 
...
但是我想在许多不同的
UIViewController
中使用相同的
UIView
,所以我实际上不想要文件的所有者,除了类本身。在中,他将
UIView
本身设置为文件的所有者,但没有成功

在那里的答案中,我找到了一个解决方案,将文件的所有者设置为零。为此,我必须将所有调用的
UIViewController
对象从Interface Builder对象库添加到InfoView.xib文件中,并将它们与
InfoView
插座连接起来

但这感觉不对所以我想在这里收集解决方案
UIView
与他的xib文件封装在一起,以便在许多不同的视图控制器中使用它。你们是怎么处理的?

谢谢你的帮助

编辑:


infoView
类似于一个覆盖,当用户按下其中一个视图控制器上的按钮时,它就会出现。它不是视图控制器的“主”视图。它提供有关其superviews视图控制器视图的详细信息,随后将消失。我只使用不同的内容填充
infoView
,所有调用的视图控制器都被丢弃。

infoView需要是子视图吗

在viewController中:

-(id) init {
    self = [super initWithNibName:@"myNib" bundle:nil]; 
    if (self) {
        // code here
    }
}

因此,您希望从要在多个
UIViewController
中使用的nib加载
UIView
,并将其连接到每个视图控制器上的插座。对吗

然后用
IBOutlet
属性创建一个
UIViewController
子类(我们称之为
FakeViewController
)。将该
FakeViewController
设置为nib文件的所有者,并将您的
UIView
连接到其出口

完成了

您只需确保所有其他视图控制器也具有这些outlet属性(尽管它们不需要是
IBOutlets
),但nib加载程序不会实际检查以确保传递到
owner
参数的类等于您在Interface Builder中指定的类名。所以你可以假装

哦,如果您是OS4.0或更高版本,请使用
UINib
加载nib文件。

就像Hollence指出的那样,我正在使用
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];

另一种方法是基于
NSObject
创建自己的“控制器”,以定义自己的生命周期(而不是标准的
UIViewController
生命周期)

例如:

BaseSubview.h:

@interface BaseSubview : NSObject {
    UIView* _view;
}

@property (nonatomic, retain) IBOutlet UIView* view;

- (void)myMethod;

@end
#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
#import "BaseSubview"
@interface InfoView : BaseSubview {
    UILabel* _labelInfo;
}

@property (nonatomic, retain) IBOutlet UILabel* labelInfo;

@end
#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
// ...
// among other var definitions
InfoView* _infoView;
// ...
BaseSubview.m:

@interface BaseSubview : NSObject {
    UIView* _view;
}

@property (nonatomic, retain) IBOutlet UIView* view;

- (void)myMethod;

@end
#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
#import "BaseSubview"
@interface InfoView : BaseSubview {
    UILabel* _labelInfo;
}

@property (nonatomic, retain) IBOutlet UILabel* labelInfo;

@end
#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
// ...
// among other var definitions
InfoView* _infoView;
// ...
InfoView.h:

@interface BaseSubview : NSObject {
    UIView* _view;
}

@property (nonatomic, retain) IBOutlet UIView* view;

- (void)myMethod;

@end
#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
#import "BaseSubview"
@interface InfoView : BaseSubview {
    UILabel* _labelInfo;
}

@property (nonatomic, retain) IBOutlet UILabel* labelInfo;

@end
#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
// ...
// among other var definitions
InfoView* _infoView;
// ...
InfoView.m:

@interface BaseSubview : NSObject {
    UIView* _view;
}

@property (nonatomic, retain) IBOutlet UIView* view;

- (void)myMethod;

@end
#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
#import "BaseSubview"
@interface InfoView : BaseSubview {
    UILabel* _labelInfo;
}

@property (nonatomic, retain) IBOutlet UILabel* labelInfo;

@end
#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
// ...
// among other var definitions
InfoView* _infoView;
// ...
InfoView.xib:

@interface BaseSubview : NSObject {
    UIView* _view;
}

@property (nonatomic, retain) IBOutlet UIView* view;

- (void)myMethod;

@end
#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
#import "BaseSubview"
@interface InfoView : BaseSubview {
    UILabel* _labelInfo;
}

@property (nonatomic, retain) IBOutlet UILabel* labelInfo;

@end
#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
// ...
// among other var definitions
InfoView* _infoView;
// ...
  • 文件所有者是InfoView
  • 照常分配门店
  • 视图是所有其他控件(如标签等)的父控件。
HugeAndComplementedViewController.h:

@interface BaseSubview : NSObject {
    UIView* _view;
}

@property (nonatomic, retain) IBOutlet UIView* view;

- (void)myMethod;

@end
#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
#import "BaseSubview"
@interface InfoView : BaseSubview {
    UILabel* _labelInfo;
}

@property (nonatomic, retain) IBOutlet UILabel* labelInfo;

@end
#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
// ...
// among other var definitions
InfoView* _infoView;
// ...
HugeAndComplementedViewController.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];

所以现在您有了自己的子视图,逻辑和设计与“庞大而复杂”的视图控制器分离。它可以具有当前项目所需的任何生命周期。

是的,它必须是子视图。这对我的问题不起作用。infoView不是viewController的“主”视图。它更多的是一个叠加,按需显示,例如按信息按钮。多多少少有点像UIAlertView…你明白我的意思了!虽然我喜欢您使用face ViewController的想法,但这种方法感觉不太正确,因为在示例中,他们说:“您不应该使用多个自定义视图控制器来管理同一视图层次结构的不同部分”。但是非常感谢您指出UINib类!在我的理解中,UIViewController类似于UIView,具有额外的层次逻辑,我不需要在屏幕上显示部分视图。FakeViewController仅用于将UIView连接到您正在加载它的任何视图控制器的出口。因此,您可以让ViewControllerA、ViewControllerB和ViewControllerC加载UIView,即使它们是不同的类。UIView认为它正在加载到FakeViewController中,但实际上没有FakeViewController的实例,您正在将它加载到ViewControllerA/B/C中。好的,谢谢!因此,您认为这种方法比我在上面描述的方法更有效吗?我在上面描述的方法是将视图控制器对象添加到xib文件中,以便将每个视图控制器的出口与视图连接起来?是的。虽然我不确定你是如何添加所有这些视图控制器的;作为真实视图控制器对象还是占位符?您可能对我在回答这个问题时所描述的“具有xib的可重用UIView小部件”问题的解决方案感兴趣:@Bogatyr thx,这是一个很好的答案。