UICollectionView crash on unhighlightAllItems

前端 未结 4 1061
别那么骄傲
别那么骄傲 2021-02-09 01:26

I\'ve gotten several crash reports related to a UICollectionView in iOS 7. I\'m not able to consistently recreate this crash.

Exception Type:  SIGSEGV
Exception         


        
相关标签:
4条回答
  • 2021-02-09 01:40

    I had this problem, though slightly different crash. Fixed by holding off any reloadData until the highlight is cleared. While toostn's suggestion would fix the issue, it is useful to be able to reloadData whilst scrolling, but doesn't make much sense when highlighting - as you have your finger on a cell.

    implement the following UICollectionViewDelegate methods:

    - (BOOL)collectionView:(UICollectionView *)collectionView shouldHighlightItemAtIndexPath:(NSIndexPath *)indexPath {
        self.allowReload = NO;
        return YES;
    }
    
    
    - (void)collectionView:(UICollectionView *)collectionView didUnhighlightItemAtIndexPath:(NSIndexPath *)indexPath {
        self.allowReload = YES;
        [self reloadIfNecessary]; // calls reloadData if it is necessary to do so!
    }
    
    0 讨论(0)
  • 2021-02-09 01:40

    I also had this crash in _unhighlightAllItems in a collection view where I used a long press recognizer that changes the state of cells (but not their number) and then called [collectionView reloadData]. In my case, the solution from @toostn (using performBatchUpdates) works great.

    I also found that using reloadItemsAtIndexPaths: instead of reloadData also avoids the crash.

    0 讨论(0)
  • 2021-02-09 01:53

    If you are calling reloadData while the user is dragging the view, that might be the reason.

    I had crashes related to this with similar crash reports and "fixed" the issue by delaying the reloadData call until after the user has finished scrolling the view. E.g. create a wrapped method instead of calling reloadData directly.

    - (void)updateData {
         if (self.collectionView.isTracking) {
             self.updateDataOnScrollingEnded = YES;
         } else {
             [self.collectionView reloadData];
         }
    }
    

    Then when scrolling ends, call the updateData method (if needed) from the scroll view's delegate methods.

    - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
    {
        if (!decelerate) {
            [self scrollViewStopped:scrollView];
        }
    }
    
    - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
    {
        [self scrollViewStopped:scrollView];
    }
    
    - (void)scrollViewStopped:(UIScrollView *)scrollView
    {
        if (self.updateDataOnScrollingEnded) {
             [self updateData];
             self.updateDataOnScrollingEnded = NO;
         }
    }
    

    My guess is that there is a weak reference to the highlighted cell's indexPath somewhere inside of the collectionView, and that calling reload will dealloc that indexPath. When the collectionView then tries to unhighlight the cell, it crashes.

    EDIT:

    As mentioned in comments below, this "solution" has some flaws. While investigating the issue further, it seems that in my case the problem had to do with multiple reloadData calls being queued on the main thread during the dragging of the collection view. When there was only one reloadData call, everything was fine, but whenever there was more than one – crash!

    Since I always had exactly one section in my collectionView i replaced the reloadData call with

    reloadSections:[NSIndexSet indexSetWithIndex:0]
    

    However, this causes the cells to quickly fade out and back in again which I avoided with the following method (it would probably be better off as a category on the collection view)

    - (void)reloadCollectionView:(UICollectionView *)collectionView animated:(BOOL)animated
    {
        [UIView setAnimationsEnabled:animated];
        [collectionView performBatchUpdates:^{
            [collectionView reloadSections:[NSIndexSet indexSetWithIndex:0]];
        } completion:^(BOOL finished) {
            [UIView setAnimationsEnabled:YES];
        }];
    }
    

    So far, this has worked well for me and it also allows for the data to actually be updated while scrolling.

    0 讨论(0)
  • 2021-02-09 01:56

    Not sure after identifying only this piece of code. But as crash signal (SIGSEGV) seems due to memory leak. You just go to your Xcode setting and inside Edit Scheme jsut enable Zombie option and then try to reproduce your crash. It will show you the controller class name of method or any crash related information inside console of Xcode. And also just try to modify you condition below:-

    - (void)setHighlighted:(BOOL)highlighted {
    
         //just comment this line or write this line to the below and check
         //[super setHighlighted:highlighted];
        if (highlighted) {
            self.alpha = 0.8;
        } else {
            self.alpha = 1.0;
        }
        [super setHighlighted:highlighted];
    }
    
    0 讨论(0)
提交回复
热议问题