在IB中,UICollectionView没有包含UICollectionViewCell。

22

我正在尝试在IB中向.nib文件添加一个UICollectionView。我已经完成了一些教程,没有遇到问题。

在我的现有应用程序中,在IB中将collection view拖入视图中并展开对象时,CollectionView Flow Layout存在,但没有collection view cell。我也无法将单元格拖放到集合视图中。此外,集合视图的显示方式不同,显示了一个网格单元的图像,而不是正常的白色框。

我尝试创建一个新的带有nib的视图控制器,并在添加collectionView时得到了相同的结果。

这个应用程序之前的部署目标是iOS 4.2,但我已将部署目标更改为iOS 6。

在任何新创建的项目中,我都不会出现这种行为。


7
好的,看起来你只能在故事板中使用IB完全布局一个UICollectionView。在.nib文件中,你会得到我上面描述的行为。在故事板中,你会得到带有你的UICollectionView的UICollectionViewCell。这是怎么回事? - Alpinista
我也遇到了同样的问题,相当烦人。 - adit
即使在Storyboard中,您也无法将集合视图单元格拖放到集合视图对象中。不确定原因。 - theiOSguy
我也遇到了这个问题。 - Akbar Khan
4个回答

9
我不能告诉你为什么它不起作用,但对我来说,这篇博客文章中的子类方法解决了问题: http://www.adoptioncurve.net/archives/2012/09/a-simple-uicollectionview-tutorial.php 以下是简要概述:
创建一个新的类MyViewCell,它扩展了UICollectionViewCell,并根据需要创建属性、操作、输出和方法。 @interface MyViewCell : UICollectionViewCell
  • create a View (xib file) with a Collection View Cell as its root object (and delete the object which is created by default).
  • in the attributes set the custom class of this Collection View Cell to your extended class MyViewCell (instead of the default UICollectionViewCell).
  • in the attributes under Collection Reusable View define an Identifier, e.g. myCell, you will need this later to register your call.
  • go back to your custom class and modify the inithWithFrame method to load and use your created view.

    - (id)initWithFrame:(CGRect)frame 
    { 
       self = [super initWithFrame:frame]; 
       if (self) 
       { 
         // Initialization code 
         NSArray *arrayOfViews = [[NSBundle mainBundle] loadNibNamed:@"CVCell" owner:self options:nil];
    
         if ([arrayOfViews count] < 1) { return nil; }
    
         if (![[arrayOfViews objectAtIndex:0] isKindOfClass:[UICollectionViewCell class]]) { return nil; }
    
         self = [arrayOfViews objectAtIndex:0];
       }
       return self;
    }
    
  • then you can register this class to be used by the collectionView with

[self.collectionView registerClass:[MyViewCell class] forCellWithReuseIdentifier:@"myCell"];

可以注册一个名为“myCell”的自定义单元格类MyViewCell,以供集合视图collectionView重用。


虽然这理论上回答了问题,但最好在此处包含答案的基本部分,并提供参考链接。 - Shawn Chin
我已经在答案中添加了更多细节。 - DELUXEnized
太棒了!只是不要忘记注册collectionView:[self.collectionView registerClass:[MyViewCell class] forCellWithReuseIdentifier:@“myCell”]; - atulkhatri

9

这个问题已经有一段时间了,但我最近遇到了同样的问题。

最终,我在这里找到了答案。

简而言之:

  • 如果您在一个.xib文件中,就不能将UICollectionViewCell拖放到UICollectionView中。只有在storyboard中才可以实现。

  • 解决方法是为自定义单元格创建.xib文件,并使用以下代码手动注册单元格:

    [self.collectionView registerClass:[CollectionViewCell class] forCellWithReuseIdentifier:CELL_ID];


1
这在Xcode 8.2.1上仍然是一个问题。我认为我们必须永远使用这个解决方法。 - Samuel Cai
为了解决这个问题,我必须使用registerNib,否则dequeueReusableCell只是一个空视图,没有任何在xib中配置的信息。 - Samuel Cai

3

将您的单元格视图定义在一个单独的nib文件中。该视图必须是UICollectionViewCell或其子类。

然后,您必须向您的集合视图注册该nib:

- (void)viewDidLoad
{
    UINib *cellNib = [UINib nibWithNibName:@"MyNib" bundle:nil];
    [self.collectionView registerNib:cellNib forCellWithReuseIdentifier:@"cell"];
}

2
由于某些原因,这个程序无法正常工作。在出列单元格时,会抛出一个异常:“nib must contain exactly one top level object which must be a UICollectionReusableView instance”。这真的很奇怪,因为文档中指出:“nib文件必须只包含一个顶级对象,并且该对象必须是UICollectionViewCell类型”。 - DELUXEnized
UICollectionViewCell继承自UICollectionReusableView。 - Michael Hogenson

0

虽然这些答案是正确的,但问题的根本原因相当微妙,苹果需要在日志中更新他们的错误信息。当您看到:

Unknown class MyViewCell in Interface Builder file.

实际上这意味着您的源代码缺少@implementation声明,或者.m文件尚未添加到目标中。因此,请检查您的代码并确保您有:

@implementation MyViewCell

@end

这对UITableViewCell和UICollectionViewCell都适用。

我在https://dev59.com/z3I-5IYBdhLWcg3wsKl4#12755891中详细讨论了一般情况下的问题。

有趣的是,如果你缺少@implementation并调用:

[self.myCollectionView registerClass:[MyViewCell class] forCellWithReuseIdentifier:@"MyViewCell"];

你将会看到:

Undefined symbols for architecture armv7:
  "_OBJC_CLASS_$_MyViewCell", referenced from:
      objc-class-ref in MyViewController.o
ld: symbol(s) not found for architecture armv7
clang: error: linker command failed with exit code 1 (use -v to see invocation)

所以苹果公司知道这个问题,只是在编译过程中没有检测到。我建议不要将自定义单元格放在单独的nib文件中,也不要调用registerClass:forCellWithReuseIdentifier:方法。在Interface Builder中,将自定义单元格直接存储在其容器UICollectionView或UITableView中会更加清晰简洁。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接