我有一个包含自定义UICollectionViewCells的UICollectionView(TestReceiptCell是类名)。
当自定义单元格仅包含UILabel时,我没有遇到任何问题让UICollectionView出现并加载自定义单元格。
然后我通过IB将UITableView添加到TestReceiptCell NIB文件中。我在TestReceiptCell.h中为UITableView设置了一个引用插座,并在.m文件中合成。我将UITableView的委托和数据源设置为包含UICollectionView的ViewController。
现在运行应用程序时,我在第三行的这个块中得到一个EXC_ BAD_ ACCESS异常:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
static NSString *cellIdentifier = @"TestReceiptCell";
TestReceiptCell *cell = (TestReceiptCell *)[collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath]; //exception thrown here
return cell;
}
我运行Zombie Instrument测试,发现释放的内存调用来自此处。这是我第一次使用该仪器,所以我不确定如何从这里进行调查。
供参考,以下是代码中一些更相关的部分:
ViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
[self.myCollectionView registerNib:[UINib nibWithNibName:@"TestReceiptCell" bundle:nil] forCellWithReuseIdentifier:@"TestReceiptCell"];
// Setup flowlayout
myCollectionViewFlowLayout = [[UICollectionViewFlowLayout alloc] init];
[myCollectionViewFlowLayout setItemSize:CGSizeMake(310, 410)];
[myCollectionViewFlowLayout setScrollDirection:UICollectionViewScrollDirectionHorizontal];
[self.myCollectionView setCollectionViewLayout:myCollectionViewFlowLayout];
self.myCollectionView.pagingEnabled = YES;
}
我正在ViewController.m文件中实现UITableView数据源和委托方法,但我不确定问题是否存在于EXC_BAD_ACCESS异常的起源:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = nil;
cell = [tableView dequeueReusableCellWithIdentifier:@"eventCell"];
if(!cell){
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"eventCell"];
}
return cell;
}
更新:
如果我将cellForItemAtIndexPath更改为:
,我可以运行它- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
static NSString *cellIdentifier = @"TestReceiptCell";
//TestReceiptCell *cell = (TestReceiptCell *)[collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
TestReceiptCell *cell = [NSBundle.mainBundle loadNibNamed:@"TestReceiptCell" owner:self options:nil][0];
return cell;
}
然而,我并没有将细胞出列,并且知道这不是正确的方法。在dequeueReusableCellWithResueIdentifier创建新单元格时,initWithFrame方法中的某个地方似乎存在问题。目前这是方法:
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
NSArray *arrayOfViews = [[NSBundle mainBundle] loadNibNamed:@"TestReceiptCell" 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;
}
编辑:
如果我没有为tableview选择委托或数据源,则会加载带有tableviews的collectionview。将委托/数据源附加到文件所有者的某些操作导致错误。
答案 0 :(得分:2)
当您注册UINib以进行单元重用时,dequeueReusableCellWithReuseIdentifier:forIndexPath:是在您注册的UINib上调用instantiateWithOwner:options:的内容。无论它通过所有者,是什么成为您的笔尖中的文件所有者插座。
看来你期望文件所有者成为UICollectionView,但我认为不是。
即使它是,我认为你不应该使用UICollectionView作为每个集合单元格中包含的UITableView的委托。这将要求您的UICollectionView跟踪每个单元格中的tableViews和内容。
我建议将包含的tableView的委托设置到集合单元本身,让每个单元管理自己的tableview。
编辑:
您可以为集合视图单元定义委托协议,以将相关的表视图事件传递到集合视图。使用此方法,您可以在集合视图数据源的collectionView:cellForItemAtIndexPath方法中为每个集合单元设置您为其定义的委托属性。
例如,当用户从表中选择一个项目时,您可以调用单元格委托来通知集合视图选择了哪个项目。
此方法允许您抽象收集单元格使用表格视图显示单元格信息的事实。稍后,如果您决定使用嵌入式UICollectionView来显示这些项目,则委托协议可以保持不变,您可以将更改隔离到收集单元格。