展示模态视图控制器时发生奇怪的崩溃

6

我曾经看到过这个崩溃报告几次。它非常随机和罕见,我无法理解。我所做的一切就是使用以下代码展示一个模态视图控制器:

ComposeController *newcontrol = [[ComposeController alloc]initWithMode:1 withNIB:@"ComposeController"];
newcontrol.delegate = self;

UINavigationController  *holder = [[UINavigationController alloc] initWithRootViewController:newcontrol];
[self presentViewController:holder animated:YES completion:NULL];

某种方式,这完全是随机的,导致了这个结果:
OS Version:      iPhone OS 6.1 (10B143)
Report Version:  104

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

Thread 0 Crashed:
0   libobjc.A.dylib                     0x3b25c5d0 objc_msgSend + 16
1   CoreFoundation                      0x334ba73f -[__NSPlaceholderArray initWithObjects:count:] + 271
2   CoreFoundation                      0x334bae09 +[NSArray arrayWithObject:] + 45
3   UIKit                               0x353e80ab -[UIWindow _rotationViewControllers] + 51
4   UIKit                               0x353e7fe3 -[UIViewController viewControllerForRotation] + 91
5   UIKit                               0x353e7f39 -[UIViewController _visibleView] + 97
6   UIKit                               0x3546c05b -[UIWindowController transition:fromViewController:toViewController:target:didEndSelector:] + 2483
7   UIKit                               0x3546afab -[UIViewController presentViewController:withTransition:completion:] + 3399
8   MyApp                               0x00046e97 -[Inbox composeHit] (Inbox.m:207)
2个回答

5
我经常遇到同样的问题。看起来是因为我从弹出窗口中呈现模态视图控制器,这一点没有得到很好的测试,并且触发了苹果代码中的一个错误。该错误是UIKit保留了对已被解除和释放的视图控制器的未保留引用,因此在稍后的时间会访问该引用。我的解决方法要么是避免从弹出窗口中显示模态VC,要么是无限期地保留所有这些VC(在成员变量或类似位置)。
以下是详细信息:
以下是我用于触发问题的代码。
-(void) handlePinchFromCell:(AMPSupportingPhotoCell*) cell
{
    UIViewController * vc = [[UIViewController alloc] init]; // UIViewController #0
    [self presentViewController:vc animated:YES completion:nil];
    [self performSelector:@selector(dismiss:) withObject:vc afterDelay:2];
}

-(void) dismiss:(UIViewController*)vc
{
    [self dismissViewControllerAnimated:YES completion:^(){NSLog(@"-------");}];
}

这段代码是UIViewController #1的一部分,它位于UIPopoverController中,这个popoverController是从另一个UIViewController #2弹出的,UIViewController #2本身是从另一个视图控制器UIViewController #3呈现出来的。在关闭popover后,控制器#2被解除显示后,就会发生崩溃。
如果启用Zombies,我会得到相同的堆栈跟踪,但带有以下消息:
2013-03-13 20:04:24.681 Mercury[16698:19d03] handlePinchFromCell: a225710
2013-03-13 20:04:27.083 Mercury[16698:19d03] -------
2013-03-13 20:04:31.606 Mercury[16698:19d03] *** -[UIViewController retain]: message sent to deallocated instance 0xa225710

请注意,VC #0被分配、呈现、2秒后被解散和释放,但在苹果的代码中仍然存在一个悬空引用。当弹出窗口关闭并且VC#2被解散时,整个系统会崩溃,因为试图访问已经被释放的VC。我相信这是苹果的错误。我猜想它与从弹出窗口中呈现VC有关,所以如果你避免这样做或者自己保留VC,你应该没问题。

同样问题的另一个堆栈跟踪如下。如果上面的代码运行两次,就会发生这种情况:

2013-03-13 20:12:53.883 Mercury[16735:19d03] handlePinchFromCell: 16d54da0
2013-03-13 20:12:56.285 Mercury[16735:19d03] -------
2013-03-13 20:13:03.481 Mercury[16735:19d03] handlePinchFromCell: a2565f0
2013-03-13 20:13:03.481 Mercury[16735:19d03] *** -[UIViewController isKindOfClass:]: message sent to deallocated instance 0x16d54da0
(lldb) bt
* thread #1: tid = 0x1f03, 0x017f8a97 CoreFoundation`___forwarding___ + 295, stop reason = EXC_BREAKPOINT (code=EXC_I386_BPT, subcode=0x0)
    frame #0: 0x017f8a97 CoreFoundation`___forwarding___ + 295
    frame #1: 0x017f894e CoreFoundation`_CF_forwarding_prep_0 + 14
    frame #2: 0x00c42f90 UIKit`-[UIWindowController transition:fromViewController:toViewController:target:didEndSelector:] + 907
    frame #3: 0x00a40ee3 UIKit`-[UIViewController presentViewController:withTransition:completion:] + 4521
    frame #4: 0x00a41167 UIKit`-[UIViewController presentViewController:animated:completion:] + 112
    frame #5: 0x0006c32d Mercury`-[AMPSupportingPhotosViewController handlePinchFromCell:](self=0x16d55360, _cmd=0x0007a64a, cell=0x0a22a2a0) + 205 at AMPSupportingPhotosViewController.m:184
    frame #6: 0x015336b0 libobjc.A.dylib`-[NSObject performSelector:withObject:] + 70
    frame #7: 0x0006f317 Mercury`-[AMPSupportingPhotoCell handlePinch:](self=0x0a22a2a0, _cmd=0x00efb0db, sender=0x0a2504a0) + 215 at AMPSupportingPhotoCell.m:53
    frame #8: 0x00c2185a UIKit`_UIGestureRecognizerSendActions + 139

确实很有趣。在我的情况下,我正在从另一个模态视图控制器中呈现模态视图控制器。你觉得这是同样的问题吗?它们总是按正确的顺序被释放,但根据你所说的,似乎如果有人在第一个模态控制器上点击取消,然后迅速在原始模态控制器上点击取消,那么可能会触发崩溃? - T.Leavy
我认为这是同样的事情 - VC 在苹果系统中卡住了。 - DenNukem
我想用叉勺戳自己的眼窝。谢谢你的回答。 - Isaaс Weisberg

-3

试着这样做

[holder pushViewController:newcontrol animated:YES completion:NULL];


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接