覆盖的initWithCoder时无限循环(Infinite loop when overridin

2019-06-26 05:21发布

我有一个UIViewController与一些控制器和一些看法。 这些视图(单元格)两个是其它碎粒。 我得从网格单元网点文件拥有者,但他们不会自动加载。

所以我尝试重写GridCell.minitWithCoder 。 这将启动一个无限循环。

我知道这可能只是覆盖initWithFrame和代码添加子视图,但这不是我想要的。 我希望能够在Interface Builder中四处移动视图,且具有Xcode的初始化右侧框架中的视图。

我如何去实现呢?

编辑1

我试图把它与亚历山大的帮助工作。 这是我现在怎么得到它设置:具有的MainView用的UIView设置为栅格单元的自定义类。 它得到了在的MainView /文件的所有者的出口。

移除了所有GridCell.m初始化代码,并设立出口到我的自定义类

该的MainView不还显示栅格单元虽然。 没有错误,只是一个寂寞,空虚的空间,红色的开关应。 我究竟做错了什么?

我非常接近,只是在做这个程序。 我很想如何学习这与笔尖虽然。

Answer 1:

加载笔尖导致的initWithCoder再次调用,所以你只是想这样做,如果子类目前没有任何子视图。

-(id)initWithCoder:(NSCoder *)aDecoder {
    self = [super initWithCoder:aDecoder];
    if (self) {
        if (self.subviews.count == 0) {
            UINib *nib = [UINib nibWithNibName:NSStringFromClass([self class]) bundle:nil];
            UIView *subview = [[nib instantiateWithOwner:self options:nil] objectAtIndex:0];
            subview.frame = self.bounds;
            [self addSubview:subview];
        }
    }
    return self;
}


Answer 2:

加载笔尖将导致一个相应的所有者

  -(id) initWithCoder:(NSCoder *) coder;  

呼叫

因此,你的这个方法折轴:

self = [[[NSBundle mainBundle] loadNibNamed: @"GridCell"
owner: self
options: nil] objectAtIndex:0];

将再次导致的initWithCoder方法的调用。 那是因为你尝试再次装入笔尖。 如果定义了一个自定义的UIView,并创建一个笔尖文件布局其子视图,你不能只是增加一个UIView到另一个笔尖文件,在IB类的名称更改为您的自定义类,并期望笔尖加载系统数字出来。 你可以做的是以下几点:

您的自定义视图的笔尖文件需要有“文件的所有者类设置为自定义视图类,你需要在你的自定义类的出口被称为“toplevelSubView”连接到您的自定义视图笔尖文件中的观点,即充当容器的所有子视图。 添加其他网点到您的视图类和子视图最多连接“文件的所有者”(自定义的UIView)。 (见https://stackoverflow.com/a/7589220/925622 )

编辑好了,回答你的问题,编辑我会做到以下几点:

转到要包括自定义视图与它的笔尖文件布点它笔尖文件。 不要使它的自定义视图(栅格单元)本身,而不是使其中将包含您的网格单元中的视图(gridCellContainer例如,但它应该是一个UIView)自定义视图中自定义initWithFrame方法就像你在做的initWithCoder:

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"GridCell" owner:self options:nil];    
        self = [nib objectAtIndex:0];
        self.frame = frame;
    }
    return self;
}

然后,在其中的viewController是fileOwner为要包括您的自定义视图(一个与gridCellContainer视图)认为这样做是viewDidLoad中如

//...
GridCell *gridCell = [[GridCell alloc] initWithFrame:self.viewGridCellContainer.bounds];
[self.viewGridCellContainer addSubview:gridCell];

现在eveything应按照您预期



Answer 3:

文件的所有者不会得到一个呼叫

  -(id) initWithCoder:(NSCoder *) coder;  

加载厦门国际银行的时候。

然而, 在厦门国际银行定义的每个视图将得到一个呼叫

-(id) initWithCoder:(NSCoder *) coder;  

加载厦门国际银行的时候。

如果你有在厦门国际银行定义一个UIView(即栅格单元)的一个子类,还尝试加载你的子类的的initWithCoder同一厦门国际银行,你将最终获得一个无限循环。 不过,我看不到会用例是什么。

通常你设计你的UIView的子类(即栅格单元)在一个厦门国际银行,然后使用该子类在视图控制器的厦门国际银行为例。

此外,无法看到使用的情况下自定义视图将有一个子视图在它的initWithCoder,即

-(id)initWithCoder:(NSCoder *)aDecoder {
    self = [super initWithCoder:aDecoder];
    if (self) {
        if (self.subviews.count == 0) {
            UINib *nib = [UINib nibWithNibName:NSStringFromClass([self class]) bundle:nil];
            UIView *subview = [[nib instantiateWithOwner:self options:nil] objectAtIndex:0];
            subview.frame = self.bounds;
            [self addSubview:subview];
        }
    }
    return self;
}

除非你想成为能够覆盖在其他一些厦门国际银行需求的视图层次。 其中IMO假定外部依赖性(即,在另一XIB所定义的分层结构),并有点违背了在第一位置的可重复使用的UIView的目的。

记住该裸加载厦门国际银行时,通过一个实例作为文件的所有者,将其所有IBOutlet中(S)组。 在这种情况下,你会被替换自我(即栅格单元)与任何在GridCell.xib根的观点是,失去了在这个过程中的所有IBOutlet中的连接。

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"GridCell" owner:self options:nil];    
        self = [nib objectAtIndex:0];
        self.frame = frame;
    }
    return self;
}

还有的是“更详细的岗位如何实现可重复使用的UIView。 ”该进入更详细一点的很好,希望清除的东西了。



Answer 4:

loadNibNamed ::将调用的initWithCoder:

你为什么不遵循这种模式?

-(id)initWithCoder:(NSCoder *)coder
{

    if (self = [super initWithcoder:coder]) {

       // do stuff here ... 

    }

    return self;                 
}

请问[super initWithcoder:coder]做,你想避免的事情?



Answer 5:

我已经当我试图覆盖同样的问题initWithsomething方法,我们需要

-(id)initWithsomething:(Something *)something
{
    if (self = [super initWithsomething:something]) {
       // do stuff here ... 
    }

    return self; 
}

代替

-(id)initWithsomething:(Something *)something
{
    if (self = [super init]) {
       // do stuff here ... 
    }

    return self;
}


文章来源: Infinite loop when overriding initWithCoder