IOS UICollectionView 在使用两个集合视图时抛出断言

Posted

技术标签:

【中文标题】IOS UICollectionView 在使用两个集合视图时抛出断言【英文标题】:IOS UICollectionView throws assertion when using two collection views 【发布时间】:2017-04-03 22:43:44 【问题描述】:

我在一个 UIViewController 中有两个 UICollectionView。我用标签号分隔它们,以便我可以同时使用数据源和委托方法。但是,当我运行代码时,它会因异常而崩溃:

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'UICollectionView received layout attributes for a cell with an index path that does not exist: <NSIndexPath: 0xc000000000200016> length = 2, path = 0 - 1'.

我在论坛中查找了这个,大多数人说你需要使 UIControllerView 无效然后重新加载,但在我的情况下这不起作用。

有人知道如何解决这个问题吗?

这是我的代码:

-(void)viewDidLoad 

    self.socialMediaGrayIcons = [[NSMutableArray alloc] initWithObjects:[UIImage imageNamed:@"fb-gray.png"],
                            [UIImage imageNamed:@"twitter-gray.png"],
                            [UIImage imageNamed:@"insta-gray.png"],
                            [UIImage imageNamed:@"sms-gray.png"],
                            [UIImage imageNamed:@"email-gray.png"], nil];

    // setup collection view
    self.avatarCollectionView.tag = 200;
    self.socialMediaCollectionView.tag = 201;

    UINib *cellNib = [UINib nibWithNibName:@"NibCell" bundle:nil];
    [self.avatarCollectionView  registerNib:cellNib forCellWithReuseIdentifier:@"cvCell"];
    [self.socialMediaCollectionView  registerNib:cellNib forCellWithReuseIdentifier:@"smCell"];

    // setup collection view layout
    UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init];
    [flowLayout setItemSize:CGSizeMake(40, 40)];
    [flowLayout setScrollDirection:UICollectionViewScrollDirectionHorizontal];

    [self.avatarCollectionView setCollectionViewLayout:flowLayout];
    [self.socialMediaCollectionView setCollectionViewLayout:flowLayout];

    [self.avatarCollectionView reloadData];
    [self.avatarCollectionView.collectionViewLayout invalidateLayout];

    [self.socialMediaCollectionView reloadData];
    [self.socialMediaCollectionView.collectionViewLayout invalidateLayout];


....

#pragma mark UICollectionView DataSource and Delegate mathods
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView

    return 1;


- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section

    if (collectionView.tag == 200)
    
        return self.children.count;
     else if (collectionView.tag == 201)
        return self.socialMediaGrayIcons.count;
    

    return 1;



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

    UICollectionViewCell *cell;

    if (collectionView.tag == 200)
    
        static NSString *cellIdentifier = @"cvCell";
        cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];

        Child *currentChild = [self.children objectAtIndex:indexPath.row];


        UIImage *curImage = [UIImage imageWithData:currentChild.thumbnail];
        UIImageView *thumbView = (UIImageView *)[cell viewWithTag:100];

        if (curImage != nil)
        
            [thumbView setImage:curImage];

        
     else if (collectionView.tag == 201)

        static NSString *cellIdentifier = @"smCell";
        cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];

        UIImage *curImage = (UIImage*) [self.socialMediaGrayIcons objectAtIndex:indexPath.row];
        UIImageView *thumbView = (UIImageView *)[cell viewWithTag:101];

        if (curImage != nil)
        
            [thumbView setImage:curImage];

        
    

    return cell;

【问题讨论】:

这里有一些证据表明您的 numberOfItemsInSection 正在落入底部的荒谬 return 1 并且其中一个数组有 0 个元素。 不要使用标签。只需将每个集合视图存储为属性,然后将收到的 collectionview 参数与属性进行比较,以确定您被询问的集合视图 这个Answer 涵盖了您的问题。希望对您有所帮助... 【参考方案1】:

采纳@Paulw 的好建议如下所示:

@property(weak,nonatomic) IBOutlet UICollectionView *collectionViewA;
@property(weak,nonatomic) IBOutlet UICollectionView *collectionViewB;

您的数据源方法必须严格按照传递的集合视图将条件划分为两个分支,并且始终在一个中使用一个数据源数组,在另一个中使用另一个。

您可以通过始终通过方便的方法获取数据源来强制执行此宗教,例如...

- (NSArray *)datasourceForCollectionView:(UICollectionView *)collectionView 
    if (collectionView == self.collectionViewA) 
        return self.children;
     else  // NOTICE - no else-if, there's no other valid condition
        return self.socialMediaGrayIcons;
    

在任何地方都可以使用它,例如...

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section 
    return [self datasourceForCollectionView:collectionView].count;

【讨论】:

我将如何使用方便的方法 - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath 其中一个数组包含 UIImage 对象和其他 Child 对象? 使用条件前的便捷方法获取数组。然后引用 indexPath.row 中的数组,并在每个分支中适当地转换该元素。 进行建议的更改后仍然出现同样的崩溃 添加异常断点来标识行。大约一个小时后,我将再次使用开发机器 我放了一个异常断点,但它没有显示该行..它仍然在 main 中中断。

以上是关于IOS UICollectionView 在使用两个集合视图时抛出断言的主要内容,如果未能解决你的问题,请参考以下文章

[iOS开发]UICollectionView瀑布流的学习

使用UICollectionView创建书架

UICollectionView基本使用和常用代理方法解释

使用 iOS 7 的 UICollectionView?边距空间

iOS:使用约束动画 UICollectionView 垂直扩展?

UICollectionView 显示两行,但我只想要一行