将子视图添加到 UICollectionViewCell 时出现意外行为

Posted

技术标签:

【中文标题】将子视图添加到 UICollectionViewCell 时出现意外行为【英文标题】:Unexpected behaviour when adding subviews to UICollectionViewCell 【发布时间】:2012-10-09 05:49:26 【问题描述】:

我目前在向 UICollectionViewCell 添加子视图时遇到了一个奇怪的问题,但仅限于某些情况下。

这是场景:

我有一个“容器”视图,它符合带有嵌套视图的非常特定的协议 (ADGControl),通常是 UIKit 控件子类,即 MyCustomTextField:用于自定义控件的 UITextField。

“容器”视图公开了一个名为“innerControlView”的属性,该属性持有对自定义控件的强引用,我正试图将其作为子视图添加到单元格的内容视图中。

代码如下:

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath

   FormControlCollectionViewCell *cell = [self.formCollectionView dequeueReusableCellWithReuseIdentifier:@"formControlCell" forIndexPath:indexPath];
   NSArray *sectionContents = [_controlList objectAtIndex:[indexPath section]];

   // This works
   //UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 315.0f, 30.0f)];
   //textField.borderStyle = UITextBorderStyleLine;
   //[cell.controlView addSubview:textField];

   // This doesn't (see the behaviour in video clip)
   id <ADGControl> control = [sectionContents objectAtIndex:[indexPath row]]; // The container view I'm referring to
   [cell.contentView addSubview:(UIView *)[control innerControlView]]; // [control innerControlView] is the typical UIKit control subclass for custom controls. In this example it will be a UITextField

   return cell;

正如您在上面的代码 cmets 中看到的,每当我尝试直接添加 UIKit 控件 (textField) 时,它都可以正常工作。但是,一旦我尝试添加我的自定义控件([control innerControlView],我就会在此处的视频剪辑中看到意外的行为:http://media.shinywhitebox.com/ryno-burger/ios-simulator-ios-simulator-ipad-ios-a

上面的链接只是一个 23 秒的短视频片段,以更好地展示我得到的“意外行为”。

如果有人能指出我做错了什么问题,我将不胜感激。

谢谢

【问题讨论】:

您可能想将该代码(添加子视图)移动到子类中。因为如果你这样做,它会在每次调用方法时添加它。 好吧,很酷,但我不确定在 UICollectionViewCell 的子类中添加它的位置,因为我从 dequeueReusableCellWithReuseIdentifier 获取实例:。我试过 - (id)init 但它没有被调用。使用 dequeueReusableCellWithReuseIdentifier 时,我很难理解 UICollectionViewCell 的生命周期,所以我不确定在哪里添加我的初始化代码。 对不起,我的意思是 - (id)initWithFrame。但它永远不会在调试器中达到我的断点。 【参考方案1】:

正如您在the documentation on UICollectionViewCells 中看到的那样,您不应该将内容子视图添加到单元格本身,而是添加到contentView

而且,就像我之前在评论中所说的那样,您不应该在数据源中添加子视图,而应该在子类中添加子视图。您已经注意到 initWithFrame: 没有被调用,请改用 initWithCoder:

-(id)initWithCoder:(NSCoder *)aDecoder 
    self = [super initWithCoder:aDecoder];
    if (self) 
        // Add your subviews here
        // self.contentView for content
        // self.backgroundView for the cell background
        // self.selectedBackgroundView for the selected cell background
    
    return self;

【讨论】:

我真的不喜欢在单元格本身中添加子视图,但是如果我的 uiview 被数据源填充怎么办?我的意思是我使用来自数据源的信息创建了一些。我创建了一个自定义单元类并在解码器方法中添加了视图。我还在 cellForIndexPath 方法中填充了我的视图,它没有出现。我的解码器崩溃了,说我的视图为零【参考方案2】:

一个视图一次只能在一个超级视图中。如果它已经是容器视图的子视图,则不能将其添加为另一个视图(您的单元格)的子视图。

目前还不清楚为什么要将视图用​​作模型对象的一部分,但是在将其添加到单元格之前,您要么必须更改它,要么必须从当前父视图中删除内部视图。

【讨论】:

嗨,我尝试只添加已经包含内部控制视图的容器视图,而不是直接添加内部控制视图,但仍然得到相同的行为,但略有不同。现在似乎所有文本字段都被覆盖在一个单元格上。两个视图都有相同的框架,这有关系吗?请查看更新的视频剪辑:media.shinywhitebox.com/ryno-burger/… GuidoH 有你在 cmets,我想。您每次都添加相同的视图,即使对于重复使用的单元格也是如此。

以上是关于将子视图添加到 UICollectionViewCell 时出现意外行为的主要内容,如果未能解决你的问题,请参考以下文章

将子视图添加到 UICollectionViewCell 子类?

仅将子视图添加到当前视图的 UINavigationBar

将子视图添加到视图控制器

将子视图添加到 UIViews 数组?

如何按顺序将子视图添加到 UIScrollView

将子视图添加到 SKStoreProductViewController