UIScrollView EXC_BAD_ACCESS crash in iOS SDK

半腔热情 提交于 2019-11-29 22:12:14

The UIScrollView on stack frame #1 probably wants to inform its delegate about the animation ending, but the delegate is gone at that point. Setting NSZombieEnabled would probably confirm this.

Delegates are not retained, so this is a common error in Cocoa and Cocoa Touch. Look for delegates on UIScrollView or UITableView in your code and try to find out which one might be released before its time.

I just worked through this problem myself.

I had an issue where:

  • A scrollview delegate was wired to a UIViewController
  • The scrollview began animating
  • The delegate went away and dealloc was called.

The problem was the scrollview delegate messages were firing on a new-deallocated object, and the crash logs were a bit confusing as they were pointing to nonsensical object references.

The fix was to set the scrollview delegate to nil as the first line of my view controller dealloc method.

Hope this helps someone else!

Chip Bancroft

For completeness I'm adding this stack trace (iOS 6) for those who may encounter the same problem but with a little bit different implementation and the exact steps to reproduce the problem.

Exception Type:  EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x71f05631
Crashed Thread:  0

Thread 0 name:  Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0   libobjc.A.dylib                 0x3919b5d0 objc_msgSend + 1
1   UIKit                           0x33421830 -[UIScrollView(UIScrollViewInternal) _delegateScrollViewAnimationEnded] + 48
2   UIKit                           0x334217ba -[UIScrollView(UIScrollViewInternal) _scrollViewAnimationEnded:finished:] + 130
3   UIKit                           0x334216a4 -[UIAnimator stopAnimation:] + 460

This is happening on iOS 6 and started to occur when I implemented the UIScrollViewDelegate method:

" -(void)scrollViewDidEndDecelerating:(UITableView *)tableView" 
and made a call to:
"[tableView scrollToRowAtIndexPath: indexPath atScrollPosition:UITableViewScrollPositionTop animated:YES];".  

The problem occurred when the animation started and I pressed the "Back" button and my view controller was popped off before the animation completed.

When reproducing you must be sure to press the "Back" button after the the animation starts but before it completes. It took my a few tries. I tried to recreate the problem by programmatically popping the view controller off but was not able to reproduce it. I had to use the "Back" button. I had been simply calling [myTableView release] in the dealloc. The solution was as described here to set both of these properties to nil:

self.myTableView.delegate = nil;
self.myTableView = nil;

At first, delegates should be of weak/assign type. But event in this case there is a very common subtle obstacle driven by scroll animations. If you use animated content offset changes for your ScrollViews you strongly need to set its delegate to nil at dealloc method.

Otherwise you will get the following

[YourViewController respondsToSelector:]: message sent to deallocated instance

The very common example:

1. _tableView is ivar of YourViewController
2. _tableView.delegate = self;
3. - (void)scrollViewDidScroll:(UIScrollView *)scrollView is implemented at YourViewController
4. at some point you call [_tableView scrollToRowAtIndexPath:indexPath 
   atScrollPosition:UITableViewScrollPositionBottom animated:YES];
   or [_tableView setContentOffset:CGPoint animated:YES]
   and try to close YourViewController

The _tableView is retained by CoreAnimation, but YourViewController is deallocated!

My guess would be that the scrollview's delegate is set to an object that has been deallocated. Try settings all the delegates of child objects to nil in your dealloc methods.

This may happen if you inserted a refresh controller into a table view as a subview (my hint, never do that)...

All above didn't fix my issue, so I dug deep my code again. I recognized that crash appears when I perform keyboard and UICollectionView animation (yeah, it's a chat) and dismiss current controller.

Application crashes because I try making scrolling in animation completion block :)

Just cut it and all work well now!

Happy coding and debugging :)

After facing the same problem I set:

self.collectionView.delegate = nil;

in - (void)viewDidLoad (before actually setting ViewController as collectionView delegate) and -(void)viewWillDisappear:(BOOL)animated

Everything works fine now.

Thanks for help.

I've seen such behaviour, when call scrollToRowAtIndexPath with not existing indexPath

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!