【问题标题】:Objective-C Bug: Wrong IndexPath on Cells with NSArrayObjective-C 错误:使用 NSArray 的单元格上的 IndexPath 错误
【发布时间】:2020-06-30 16:19:37
【问题描述】:

我在我的代码中通过 Swift Bridging 为我的 CollectionView 使用 CardsCollectionViewLayout

Objective-C(不工作)

我的问题是 IndexPath 返回错误的Item 索引。这是最小的代码:

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.collectionViewEvents.collectionViewLayout = [[CardsCollectionViewLayout alloc] init];
    self.collectionViewEvents.dataSource = self;
    self.collectionViewEvents.delegate = self;
    self.collectionViewEvents.pagingEnabled = YES;
    self.collectionViewEvents.showsHorizontalScrollIndicator = NO;

    [self load];
}

// Issue visible here, the indexPath.item is not correct
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    for (UICollectionViewCell *cell in self.collectionViewEvents.visibleCells) {
        NSIndexPath *indexPath = [[self collectionViewEvents] indexPathForCell:cell];
        NSLog(@"Visible Cell IndexPath Item %ld", indexPath.item);
        return;
    }
}

- (void)load
{

    // self.eventData is declares as: @property (nonatomic) NSArray *eventData;
    self.eventData = [[NSArray alloc] initWithObjects:UIColor.blackColor, UIColor.whiteColor, UIColor.brownColor, nil];
    [[self collectionViewEvents] reloadData];
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"CollectionViewCellReuseIdentifier"
                                                                           forIndexPath:indexPath];

    cell.layer.cornerRadius = 7.0;
    cell.backgroundColor = UIColor.blackColor;

    return cell;
}

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
    return self.eventData.count;
}

结果(注意第一个和第二个单元格如何具有相同的 IndexPath 项):

2020-03-19 14:48:05.334905+0100 App[7422:2617858] Visible Cell IndexPath Item 2 # => 3rd cell
2020-03-19 14:48:05.741805+0100 App[7422:2617858] Visible Cell IndexPath Item 1 # => 2nd cell
2020-03-19 14:48:06.184932+0100 App[7422:2617858] Visible Cell IndexPath Item 1 # => 1st cell

斯威夫特(工作)

我从他的代码库中尝试了this Example,它静态声明了colors

  var colors: [UIColor]  = [
    UIColor(red: 237, green: 37, blue: 78),
    UIColor(red: 249, green: 220, blue: 92),
    UIColor(red: 194, green: 234, blue: 189),
    UIColor(red: 1, green: 25, blue: 54),
    UIColor(red: 255, green: 184, blue: 209)
  ]
...

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCellReuseIdentifier", for: indexPath)

        cell.layer.cornerRadius = 7.0
        cell.backgroundColor = .black

        return cell
    }

在执行下面这段代码后,它会返回正确的 IndexPath。

    // Issue NOT visible here, the indexPath.item IS correct
    func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {

        for cell in collectionView.visibleCells {
            let indexPath = collectionView.indexPath(for: cell)
            print(indexPath?.item)
            return
        }
    }

结果

2020-03-19 14:48:05.334905+0100 App[7422:2617858] Visible Cell IndexPath Item 2 # => 3rd cell
2020-03-19 14:48:05.741805+0100 App[7422:2617858] Visible Cell IndexPath Item 1 # => 2nd cell
2020-03-19 14:48:06.184932+0100 App[7422:2617858] Visible Cell IndexPath Item 0 # => 1st cell

我在Objective-C 代码中做错了什么?


我尝试过的事情

// 1st cell has index 1, instead of 0
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    for (UICollectionViewCell *cell in [[self collectionViewEvents] visibleCells]) {
        NSIndexPath *indexPath = [[self collectionViewEvents] indexPathForCell:cell];
        NSLog(@"Visible Cell IndexPath Item %ld", indexPath.item);
        return;
    }
// 1st cell has index 1, instead of 0
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    NSArray *visible = [self.collectionViewEvents indexPathsForVisibleItems];
    NSIndexPath *indexPath = [visible firstObject];
    NSLog(@"Visible Cell IndexPath Item %ld", indexPath.item);
    return;
// Calling it in main thread, same result
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    dispatch_async(dispatch_get_main_queue(), ^{
        for (UICollectionViewCell *cell in [[self collectionViewEvents] visibleCells]) {
            NSIndexPath *indexPath = [[self collectionViewEvents] indexPathForCell:cell];
            NSLog(@"Visible Cell IndexPath Item %ld", indexPath.item);
            return;
        }
    });

【问题讨论】:

  • 检查答案我认为您的问题是您没有将数据源设置为您的收藏视图
  • @Was'SiimBenHssen 为您的评论添加了说明并修复了 Swift 代码。我不是要设置 backgroundColor,而是要在 Objective-C 代码中获得正确的 IndexPath.item
  • 您是否尝试过使用[[self collectionViewEvents] indexPathsForVisibleItems]?可能是 indexPaths 尚未更新,您可能需要将您的 for 循环排入主队列的末尾 (dispatch_async(dispatch_get_main_queue(), ^{ for... }))。
  • @AlejandroIván 刚刚尝试过,请检查问题的结尾。没有帮助。
  • 您是否可以在循环遍历单元格时也尝试打印单元格本身?我现在能想到的唯一解释是,当你迭代它们时,可见单元格会因某种原因发生变化,但这似乎不太可能。

标签: ios objective-c swift uicollectionview uicollectionviewcell


【解决方案1】:

问题是你在这个循环中有一个返回。

for (UICollectionViewCell *cell in [[self collectionViewEvents] visibleCells]) {
    NSIndexPath *indexPath = [[self collectionViewEvents] indexPathForCell:cell];
    NSLog(@"Visible Cell IndexPath Item %ld", indexPath.item);
    return; // <- This here
}

visibleCells 返回集合中所有可见单元格的数组。您只 NSLog 该数组中的第一项,因此这取决于您滚动到哪个位置将是第一个。

【讨论】:

  • 回报必须在那里。与 Swift 示例相同的代码(我实际上想要在第一个项目上尽早返回)。问题在于不同卡片上的索引错误,使用相同的 Objective-C 和 Swift 代码。请参阅我再次发布的示例。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-02
  • 2012-07-10
  • 2011-05-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多