为什么当Custom UIView从NIB加载自身但是也嵌入另一个NIB时我得到无限循环

时间:2012-05-11 14:08:16

标签: ios objective-c uiview

自定义uiview(MyCustomView)从NIB(MyCustomView.xib)加载其视图时遇到问题。

问题是MyCustomView在其他XIB中重用,因此调用了awakeFromNib。 CustomView.xib还包含一个MyCustomView实例,因此MyCustomView.awakeFromNib中的loadNibNamed进入无限循环

我得到无限循环:

SomeVC.xib
+ calls MyCustomView awakeFromNib
++ which calls loadNibNamed: MyCustomView.nib
+++++ but top level View is also instance of MyCustomView
....so awakeFromNib: goes into infinite loop

我只是想知道当一个自定义视图从一个nib加载它的self时,那么顶级UIView不应该是MyCustomView的实例? 如果是这样,我如何连接插座/操作(我是否将MyCustomView设为文件所有者?)

无论如何欢呼

LONG EXPLANATION:

我有一排按钮,我想在多个屏幕上重复使用。 所以我创建了一个自定义视图

@interface ScreenMenuButtonsView : UIView
@property (retain, nonatomic) IBOutlet UIButton *buttonHome;
@property (retain, nonatomic) IBOutlet UIButton *buttonMyMusic;
@property (retain, nonatomic) IBOutlet UIButton *buttonStore;
@property (retain, nonatomic) IBOutlet UIButton *buttonSocial;
@property (retain, nonatomic) IBOutlet UIButton *buttonSettings;

@end

我想在IB中布局视图,所以我创建了一个NIB

ScreenMenuButtonsView_iPad.xib

Files Owner: no set NSObject
VIEW: ScreenMenuButtonsView
+ UIButton
+ UIButton
+ UIButton

我希望自定义视图在内部加载自己的NIB,我使用了自己的示例 http://nathanhjones.com/2011/02/20/creating-reusable-uiviews-with-a-drop-shadow-tutorial/ http://nathanhjones.com/wp-content/uploads/2011/02/ReusableTableHeaders.zip

- (id)initWithFrame:(CGRect)frame {

    //self = [super initWithFrame:frame]; // not needed - thanks ddickison
    if (self) {
        NSArray *nib = [[NSBundle mainBundle] 
                        loadNibNamed:@"HeaderView"
                        owner:self
                        options:nil];

        [self release]; // release object before reassignment to avoid leak - thanks ddickison
        self = [nib objectAtIndex:0];

        self.layer.shadowColor = [[UIColor blackColor] CGColor];
        self.layer.shadowOffset = CGSizeMake(1.0, 1.0);
        self.layer.shadowOpacity = 0.40;
    }
    return self;
}

除了这个假设您在某处调用initWithFrame来实例化CustomView之外,这是可以的。 HeaderView示例调用它如下:

// load the header - this could be done in viewWillAppear as well
HeaderView *header = [[HeaderView alloc] 
                       initWithFrame:CGRectMake(0, 0, 320, 60)];
header.lblTitle.text = @"That. Just. Happened.";
tblData.tableHeaderView = header;
[header release];

我希望能够在任何其他XIB中使用我的自定义视图类

HomeScreenViewController.xib

Files Owner: HomeScreenViewController
View:
+ ....other controls
+ ScreenMenuButtonsView

问题是加载HomeScreenViewController时它在我的customView上调用awakeFromNib:

所以我将nib加载到initWithFrame并移动到一个名为setupView的方法中,并从initWithFrame和awakeFromNib中调用它

- (id) initWithFrame:(CGRect)frame
{
    if ( ( self = [super initWithFrame: frame] ) )
    {
        [self setUpView];
    }
    return self;
}

- (void)awakeFromNib
{
    [self setUpView];
}

- (void) setUpView{

    if (self) {


        NSArray* nibViewsArray = nil;
        if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad){
            //IPAD
            nibViewsArray = [[NSBundle mainBundle] loadNibNamed:@"ScreenMenuButtonsView_iPad"
                                                          owner:self
                                                        options:nil];    
...
}

我的问题是加载HomeScreenViewController.xib时:

HomeScreenViewController.xib

Files Owner: HomeScreenViewController
View:
+ ....other controls
+ ScreenMenuButtonsView

它尝试创建ScreenMenuButtonsView,因为它在NIB中 它叫 ScreenMenuButtonsView awakeFromNib

但是在这里我调用loadNibNamed:

- (void) setUpView{
    _viewSetupAlready = TRUE;
    //http://nathanhjones.com/2011/02/20/creating-reusable-uiviews-with-a-drop-shadow-tutorial/
    //self = [super initWithFrame:frame]; // not needed - thanks ddickison
    if (self) {
        NSArray* nibViewsArray = nil;
        if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad){
            //IPAD
            nibViewsArray = [[NSBundle mainBundle] loadNibNamed:@"ScreenMenuButtonsView_iPad"
                                                          owner:self
                                                        options:nil];            
        }else{
            //IPHONE
            nibViewsArray = [[NSBundle mainBundle] loadNibNamed:@"ScreenMenuButtonsView_iPhone"
                                                     owner:self
                                                   options:nil];
        }
        if(nibViewsArray){
            //[self release];   // release object before reassignment to avoid leak - thanks ddickison                
            UIView * myView  = [nibViewsArray objectAtIndex: 0];

            //Check the top level object in NIB is same type as this custom class
            //if wrong you probably forgot to use correct NIB name in loadNibNamed:
            if([myView isMemberOfClass:[self class]]){

                self = (ScreenMenuButtonsView *)myView; 

            }else{
                NSLog(@"ERROR:top level view is not same type as custom class - are you loading the correct nib filename in loadNibNamed:\n%@", myView);
            }
        }else{
            NSLog(@"ERROR:nibViewsArray is nil");
        }
    }
}

loadNibName:load

ScreenMenuButtonsView_iPad.xib

Files Owner: no set NSObject
VIEW: ScreenMenuButtonsView
+ UIButton
+ UIButton
+ UIButton

但顶视图是ScreenMenuButtonsView 所以创建一个新实例并调用awakeFromNib 我得到无限循环。

我知道为什么发生的循环和ScreenMenuButtonsView上的实例正在从xib加载另一个实例。

我的问题在

ScreenMenuButtonsView_iPad.xib

Files Owner: no set NSObject
VIEW: ScreenMenuButtonsView
+ UIButton
+ UIButton
+ UIButton
我应该改变吗?  查看:UIView

但按钮的插座和操作如何: 我应该改变吗? 文件所有者:没有设置NSObject

是视图类

文件所有者:ScreenMenuButtonsView

0 个答案:

没有答案