iOS SDK中的UIScrollView EXC_BAD_ACCESS崩溃

时间:2010-09-10 17:28:31

标签: iphone uiscrollview exc-bad-access

我有一个iPhone SDK应用程序,有多个视图在用户创建内容时出现和消失。在设备上使用该应用程序一段时间后,我遇到了以下崩溃:

Program received signal:  “EXC_BAD_ACCESS”.
(gdb) backtrace
#0  0x33369ebc in objc_msgSend ()
#1  0x320e5248 in -[UIScrollView(UIScrollViewInternal) _scrollViewAnimationEnded] ()
#2  0x338b4a14 in -[NSObject performSelector:withObject:] ()
#3  0x320e5098 in -[UIAnimator stopAnimation:] ()
#4  0x320e4b7c in -[UIAnimator(Static) _advance:] ()
#5  0x320e4a34 in LCDHeartbeatCallback ()
#6  0x34350e60 in HeartbeatVBLCallback ()
#7  0x332e91c0 in IOMobileFramebufferNotifyFunc ()
#8  0x316532f8 in ?? ()
#9  0x33866b50 in __CFMachPortPerform ()
#10 0x338ae52a in CFRunLoopRunSpecific ()
#11 0x338adc1e in CFRunLoopRunInMode ()
#12 0x3434e1c8 in GSEventRunModal ()
#13 0x32002c30 in -[UIApplication _run] ()
#14 0x32001230 in UIApplicationMain ()
#15 0x00002ff8 in main (argc=1, argv=0x2ffff550) at /Developer/svn/MyCompany/iPhone/MyApplication/Other Sources/main.m:14

从跟踪中可以看出,我的代码中唯一提到的是对main的调用。

我已从Xcode运行Build and Analyze,并将其设置为从终端运行我项目中的clang分析器,这两个都无法在代码中找到任何问题。我正在使用最近发布的iOS SDK版本(我还没有下载4.1版本,但我使用的版本是4.1之前发布的版本)。

另外,我已经使用模拟器在Instruments中运行应用程序,并且应用程序没有内存泄漏。

我即将尝试使用NSZombieEnabled变量并查看是否找到了任何内容,但问题是我需要在崩溃前使用该应用程序30到40分钟左右,我怀疑NSZombieEnabled甚至可能无法帮我找到问题。

我看到的崩溃似乎是模态视图在父视图控制器中调用委托时。然后父视图控制器在解除模态视图控制器之前进行一些处理。崩溃中有一些参考动画和滚动视图,但我不知道我可以做些什么导致那些有问题。有没有人对寻找的东西有任何建议?

编辑:我已将NSZombieEnabled标记放入应用程序,并在设备上,它在控制台中显示此消息:

2010-09-11 17:10:33.970 MyApplication[9321:207] *** 
-[MyViewController respondsToSelector:]: message 
sent to deallocated instance 0x7489480

据我所知,我将应用程序中使用的委托设置为所有类的deallocs中的nil,所以我不知道下一步要去哪里看。

我尝试在此使用malloc_history pid地址命令,但它说它无法找到进程,我尝试了9321,9321:207和207.此外,如果我尝试使用{ {1}}变量,程序将无法在设备上运行,我得到一堆MallocStackLogging无法在控制台中创建堆栈日志目录消息并导致程序崩溃。

哦,顺便说一下,我不能使用仪器中的僵尸检查,因为它似乎不适用于设备,我无法在模拟器中发生同样的崩溃。

9 个答案:

答案 0 :(得分:61)

我自己就是解决了这个问题。

我遇到了一个问题:

  • 将scrollview委托连接到UIViewController
  • scrollview开始制作动画
  • 代表离开了,dealloc被召唤了。

问题是scrollview委托消息在新释放的对象上触发,并且崩溃日志有点令人困惑,因为它们指向无意义的对象引用。

修复是将scrollview委托设置为nil作为我的视图控制器dealloc方法的第一行。

希望这有助于其他人!

答案 1 :(得分:42)

堆栈帧#1上的UIScrollView可能想要通知其委托有关动画结束的内容,但是该代表已经消失了。设置NSZombieEnabled可能会证实这一点。

不保留代理,因此这是Cocoa和Cocoa Touch中的常见错误。在代码中查找代理UIScrollViewUITableView,并尝试找出可能在其时间之前发布的代理。

答案 2 :(得分:16)

为了完整性,我正在为那些可能遇到相同问题但有一些不同的实现和重现问题的确切步骤的人添加此堆栈跟踪(iOS 6)。

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

这在iOS 6上发生,并在我实施时开始发生 UIScrollViewDelegate方法:

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

动画开始时出现问题,按下“后退”按钮,动画完成前弹出视图控制器。

复制时,必须确保在动画开始后但在完成之前按“返回”按钮。我花了几次尝试。我尝试通过以编程方式弹出视图控制器来重新创建问题,但无法重现它。我不得不使用“后退”按钮。我只是在dealloc中调用[myTableView release]。解决方案如此处所述,将这两个属性设置为nil:

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

答案 3 :(得分:7)

首先,委托应为弱/分配类型。但在这种情况下的事件是非常普遍的 滚动动画驱动的微妙障碍。如果您使用动画内容偏移更改 你的 ScrollViews 你强烈需要在 dealloc 方法中将委托设置为 nil

否则您将获得以下

[YourViewController respondsToSelector:]: message sent to deallocated instance

非常常见的例子:

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

CoreAnimation保留_tableView,但是取消分配了YourViewController!

答案 4 :(得分:3)

我的猜测是将scrollview的委托设置为已解除分配的对象。尝试在dealloc方法中将子对象的所有委托设置为nil。

答案 5 :(得分:2)

如果您将刷新控制器作为子视图插入到表视图中(我的提示,从不这样做),可能会发生这种情况......

答案 6 :(得分:2)

以上都没有解决我的问题,所以我再次深入挖掘我的代码。 我认识到当我执行键盘和 UICollectionView 动画(是的,它是聊天)并关闭当前控制器时会出现崩溃。

应用程序崩溃,因为我尝试在动画完成块中滚动:)

切断它,现在一切正常!

快乐的编码和调试:)

答案 7 :(得分:1)

面对同样的问题后,我设置了:

self.collectionView.delegate = nil;
- (void)viewDidLoad中的

(在将ViewController实际设置为collectionView委托之前)  和-(void)viewWillDisappear:(BOOL)animated

现在一切正常。

感谢您的帮助。

答案 8 :(得分:0)

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