简体   繁体   English

UICollectionView在unhighlightAllItems上崩溃

[英]UICollectionView crash on unhighlightAllItems

I've gotten several crash reports related to a UICollectionView in iOS 7. I'm not able to consistently recreate this crash. 我收到了几个与iOS 7中的UICollectionView相关的崩溃报告。我无法一致地重新创建这个崩溃。

Exception Type:  SIGSEGV
Exception Codes: SEGV_ACCERR at 0x91c4392b
Crashed Thread:  0

Application Specific Information:
*** Terminating app due to uncaught exception '', reason: ''

Thread 0 Crashed:
0   libobjc.A.dylib                     0x39dd2b26 objc_msgSend + 6
1   UIKit                               0x31fd5eef -[UICollectionView cellForItemAtIndexPath:] + 111
2   UIKit                               0x32060bfd -[UICollectionView _unhighlightItemAtIndexPath:animated:notifyDelegate:] + 149
3   UIKit                               0x32383947 -[UICollectionView _unhighlightAllItems] + 151
4   UIKit                               0x3205f9fb -[UICollectionView touchesBegan:withEvent:] + 367
5   UIKit                               0x31fcb101 forwardTouchMethod + 233
6   UIKit                               0x31fcb101 forwardTouchMethod + 233
7   UIKit                               0x31e3be4b _UIGestureRecognizerUpdate + 5523
8   UIKit                               0x31e73c41 -[UIWindow _sendGesturesForEvent:] + 773
9   UIKit                               0x31e735e7 -[UIWindow sendEvent:] + 667
10  UIKit                               0x31e48a25 -[UIApplication sendEvent:] + 197
11  UIKit                               0x31e47221 _UIApplicationHandleEventQueue + 7097
12  CoreFoundation                      0x2f69e18b __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 15
13  CoreFoundation                      0x2f69d6e1 __CFRunLoopDoSources0 + 341
14  CoreFoundation                      0x2f69be4f __CFRunLoopRun + 623
15  CoreFoundation                      0x2f606ce7 CFRunLoopRunSpecific + 523
16  CoreFoundation                      0x2f606acb CFRunLoopRunInMode + 107
17  GraphicsServices                    0x342f4283 GSEventRunModal + 139
18  UIKit                               0x31ea8a41 UIApplicationMain + 1137
19  JackThreadsIpad                     0x000922b7 main (main.m:16)

The UICollectionViewCells in the app share a common superclass that manages highlighting. 应用程序中的UICollectionViewCells共享一个管理突出显示的公共超类。 When the cell is highlighted the alpha changes. 当单元格突出显示时,alpha会发生变化。

- (void)setHighlighted:(BOOL)highlighted {
    [super setHighlighted:highlighted];

    if (highlighted) {
        self.alpha = 0.8;
    } else {
        self.alpha = 1.0;
    }
}

Could calling [super setHighlighted:highlighted] cause a crash like this? 可以调用[super setHighlighted:highlight]导致这样的崩溃吗? The app was compiled and submitted with XCode 4 and is only happening on iOS 7. Any other suggestions to figure out where this is happening. 该应用程序是使用XCode 4编译和提交的,并且仅在iOS 7上发生。还有任何其他建议可以确定这种情况发生的位置。 Thanks for your help. 谢谢你的帮助。

Edit: I was able to catch this in the debugger, but it still is not consistently reproducible. 编辑:我能够在调试器中捕获它,但它仍然不能始终如一地重现。 The crash is: 崩溃是:

[NSIndexPath section] message sent to deallocated instance XXXXXXXX

If you are calling reloadData while the user is dragging the view, that might be the reason. 如果在用户拖动视图时调用reloadData,则可能是原因。

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. 我通过类似的崩溃报告与此相关的崩溃,并通过延迟reloadData调用“修复”问题,直到用户完成滚动视图。 Eg create a wrapped method instead of calling reloadData directly. 例如,创建一个包装方法,而不是直接调用reloadData。

- (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. 然后当滚动结束时,从滚动视图的委托方法中调用updateData方法(如果需要)。

- (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. 我的猜测是在collectionView内部的某个突出显示的单元格的indexPath上有一个弱引用,而调用reload会释放该indexPath。 When the collectionView then tries to unhighlight the cell, it crashes. 当collectionView尝试取消突出显示单元格时,它会崩溃。

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. 在进一步研究这个问题时,似乎在我的情况下,问题与在拖动集合视图期间在主线程上排队的多个reloadData调用有关。 When there was only one reloadData call, everything was fine, but whenever there was more than one – crash! 当只有一个reloadData调用时,一切都很好,但只要有多个 - 崩溃!

Since I always had exactly one section in my collectionView i replaced the reloadData call with 因为我总是在我的collectionView中只有一个部分,所以用。替换了reloadData调用

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. 到目前为止,这对我来说效果很好,它还允许在滚动时实际更新数据。

Not sure after identifying only this piece of code. 在确定这段代码后不确定。 But as crash signal (SIGSEGV) seems due to memory leak. 但由于崩溃信号(SIGSEGV)似乎是由于内存泄漏造成的。 You just go to your Xcode setting and inside Edit Scheme jsut enable Zombie option and then try to reproduce your crash. 您只需转到Xcode设置,然后在Edit Scheme中启用jsut启用Zombie选项,然后尝试重现您的崩溃。 It will show you the controller class name of method or any crash related information inside console of Xcode. 它将显示方法的控制器类名称或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];
}

I had this problem, though slightly different crash. 我有这个问题,但崩溃略有不同。 Fixed by holding off any reloadData until the highlight is cleared. 通过保持任何reloadData来修复,直到高亮显示被清除。 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. 虽然toostn的建议可以解决这个问题,但是在滚动时能够重新加载数据是有用的,但在突出显示时没有多大意义 - 因为你手指放在一个单元格上。

implement the following UICollectionViewDelegate methods: 实现以下UICollectionViewDelegate方法:

- (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!
}

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] . 我也在集合视图中的_unhighlightAllItems中发生了这次崩溃,我使用了长按识别器来改变单元格的状态(但不是它们的数量),然后调用[collectionView reloadData] In my case, the solution from @toostn (using performBatchUpdates ) works great. 就我而言,来自@toostn的解决方案(使用performBatchUpdates )效果很好。

I also found that using reloadItemsAtIndexPaths: instead of reloadData also avoids the crash. 我还发现使用reloadItemsAtIndexPaths:而不是reloadData也可以避免崩溃。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM