在UIViewController被popup之后,MKMapView autorelease不会调用dealloc

我在类A中有以下代码:

UIViewController *vc = [self viewControllerForItem:item]; 

在我的应用程序委托viewControllerForItem方法返回一个UIViewController基于我的项目即

 vc = [[[MyCustomViewController alloc] init] autorelease]; return vc; 

然后我推视图控制器:

 [self.navigationController pushViewController:vc animated:YES]; 

这个VC我试图推动一个MKMapView,我在dealloc方法插入一个日志语句,看看是否被调用。 在我的记忆中,增长速度非常快。

但是,当我推入VC后添加下面的代码:

 [vc release]; 

我的MKMapView类调用dealloc方法。

当然,如果MKMapView类是我的应用程序委托返回的唯一类(或者我可以检查VC的类是否是我的MKMapView类),这将是一个简单的解决scheme。 不过,我想解决这个根本问题。

  1. 为什么在我的视图控制器上设置autorelease时,dealloc没有被调用?

  2. 即使在该vc上使用autorelease,我怎么可能将[vc release]添加到视图控制器?

谢谢

编辑:

这里有一些额外的信息。 我有我的应用程序委托viewControllerForItem类。 我将自动释放的对象返回到我的其他pipe理器类,然后我推视图控制器。 当我返回一个自动释放对象时,保留计数是否被搞乱了,然后把它推到其他类中?

这是当我推VC和mkmapview的didDissappear被调用时的backtrace / callstack:

 pushVC: ( 0 NewHampshire 0x00254cdf -[CustomViewController navigateToRowId:withLinkBehavior:animated:] + 2111 1 NewHampshire 0x002534c9 -[CustomViewController webView:shouldStartLoadWithRequest:navigationType:] + 841 2 UIKit 0x02caf288 -[UIWebView webView:decidePolicyForNavigationAction:request:frame:decisionListener:] + 318 3 UIKit 0x02cb1854 -[UIWebViewWebViewDelegate webView:decidePolicyForNavigationAction:request:frame:decisionListener:] + 77 4 CoreFoundation 0x05d0bd1d __invoking___ + 29 5 CoreFoundation 0x05d0bc2a -[NSInvocation invoke] + 362 6 CoreFoundation 0x05d0bdaa -[NSInvocation invokeWithTarget:] + 74 7 WebKit 0x0a4d811d -[_WebSafeForwarder forwardInvocation:] + 157 8 CoreFoundation 0x05d076da ___forwarding___ + 458 9 CoreFoundation 0x05d074ee _CF_forwarding_prep_0 + 14 10 CoreFoundation 0x05d0bd1d __invoking___ + 29 11 CoreFoundation 0x05d0bc2a -[NSInvocation invoke] + 362 12 WebCore 0x09533b29 _ZL20HandleDelegateSourcePv + 121 13 CoreFoundation 0x05ca083f __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 15 14 CoreFoundation 0x05ca01cb __CFRunLoopDoSources0 + 235 15 CoreFoundation 0x05cbd29e __CFRunLoopRun + 910 16 CoreFoundation 0x05cbcac3 CFRunLoopRunSpecific + 467 17 CoreFoundation 0x05cbc8db CFRunLoopRunInMode + 123 18 GraphicsServices 0x059749e2 GSEventRunModal + 192 19 GraphicsServices 0x05974809 GSEventRun + 104 20 UIKit 0x02a6ed3b UIApplicationMain + 1225 21 NewHampshire 0x000150dd main + 125 22 libdyld.dylib 0x04fab70d start + 1 ) disappear: ( 0 NewHampshire 0x0014631d -[CustomAdvancedGPSMapViewController viewDidDisappear:] + 173 1 UIKit 0x02b85bac -[UIViewController _setViewAppearState:isAnimating:] + 341 2 UIKit 0x02b86328 -[UIViewController __viewDidDisappear:] + 150 3 UIKit 0x02b86461 -[UIViewController _endAppearanceTransition:] + 306 4 UIKit 0x02ba549a -[UINavigationController navigationTransitionView:didEndTransition:fromView:toView:] + 738 5 UIKit 0x02b9d403 __49-[UINavigationController _startCustomTransition:]_block_invoke + 206 6 UIKit 0x03176740 -[_UIViewControllerTransitionContext completeTransition:] + 99 7 UIKit 0x02a63454 __53-[_UINavigationParallaxTransition animateTransition:]_block_invoke105 + 680 8 UIKit 0x02ad1005 -[UIViewAnimationBlockDelegate _didEndBlockAnimation:finished:context:] + 306 9 UIKit 0x02abac6c -[UIViewAnimationState sendDelegateAnimationDidStop:finished:] + 267 10 UIKit 0x02abaf58 -[UIViewAnimationState animationDidStop:finished:] + 80 11 QuartzCore 0x028b2a44 _ZN2CA5Layer23run_animation_callbacksEPv + 304 12 libdispatch.dylib 0x04d194b0 _dispatch_client_callout + 14 13 libdispatch.dylib 0x04d0775e _dispatch_main_queue_callback_4CF + 340 14 CoreFoundation 0x05d7ca5e __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 14 15 CoreFoundation 0x05cbd6bb __CFRunLoopRun + 1963 16 CoreFoundation 0x05cbcac3 CFRunLoopRunSpecific + 467 17 CoreFoundation 0x05cbc8db CFRunLoopRunInMode + 123 18 GraphicsServices 0x059749e2 GSEventRunModal + 192 19 GraphicsServices 0x05974809 GSEventRun + 104 20 UIKit 0x02a6ed3b UIApplicationMain + 1225 21 NewHampshire 0x0001507d main + 125 22 libdyld.dylib 0x04fab70d start + 1 ) 

解答:虽然这篇文章中的回复并没有提供我的问题的确切解决scheme,但是Darren使用仪器工具明确指引我进入了正确的方向。 我发现罪魁祸首是一个没有被正确释放的CABasicAnimation对象。

在viewWillDisappear方法中,我为CABasicAnimation对象添加了以下内容:

 self.rotationAnimation.delegate = nil; self.rotationAnimation = nil; 

使用工具来跟踪CustomAdvancedGPSMapViewController和/或MKMapView的保留/发布历史logging:

  • 在Xcode中,从菜单中select“Product> Profile”。

  • 仪器启动时,select“分配”模板。

  • 如果您的应用程序自动启动,请点击“停止”button停止它。

  • 点击Allocations仪器上的“i”button,然后选中“logging参考计数”。

  • 从菜单中select“查看>扩展详细信息”。

  • 点击“logging”button启动您的应用程序,并等待您的应用程序在模拟器中启动。

  • 在模拟器中,使用您的应用程序导航到CustomAdvancedGPSMapViewController。

  • 在乐器中,单击“暂停”button

  • 使用窗口右上方的search字段并searchCustomAdvancedGPSMapViewController。 CustomAdvancedGPSMapViewController应出现在“分配摘要”列表中。

  • 在“分配摘要”列表中,单击CustomAdvancedGPSMapViewController名称旁边的 – >箭头。 这应该显示您的应用程序中有一个CustomAdvancedGPSMapViewController实例处于活动状态。

  • 点击地址旁边的 – >箭头。 这将显示此CustomAdvancedGPSMapViewController实例的保留/发行历史logging。

  • Un-pause Instruments,返回到模拟器,并closures您的CustomAdvancedGPSMapViewController并返回到您认为控制器应该被释放的位置。

  • 返回乐器,再次点击“暂停”,并查看更新的保留/释放历史logging。

保留/发布历史中的第一个事件应该是“malloc”。 select该行,窗口右侧的Extended Detail视图将显示该分配的堆栈跟踪。 您应该在堆栈跟踪中看到自己的代码。 双击堆栈跟踪中的代码,您应该看到分配CustomAdvancedGPSMapViewController实例的代码行。

在代码视图上方,单击“历史logging”选项卡返回到历史列表。

保留/发布历史logging中的最后一个事件应该是“免费的”。 如果情况并非如此,可能会有泄漏。 检查保留/释放历史logging并查找不匹配的保留。 可能会有很多噪音,与CoreAnimation有关,等等。查找代码出现在堆栈跟踪中的事件。

将保留/发布历史logging与不泄漏的不同视图控制器进行比较。

如果CustomAdvancedGPSMapViewController没有泄漏,请尝试检查MKMapView的历史logging。

你写的代码是正确的,你不应该释放VC,因为它已经被autoreleased。

 -(UIViewController *) viewControllerForItem: (Item*)item { /* create controller for the item -- * alloc init with increase the retain count of your object by 1 * autorelease will reduce the retain count of the object by 1 */ return [[[MyCustomViewController alloc] init] autorelease]; } UIViewController *vc = [self viewControllerForItem:item]; [self.NavigationController pushViewController:vc]; 

你不能释放'vc',因为你不拥有它,因为你没有为它做'alloc init'或'retain'。

即使在发布之后,我也遇到了Mapview不能释放内存的问题。 这似乎是一个苹果的错误,这个内存将被破坏只有当你得到一个内存警告mapview。 但是你可以通过做一个黑客来强制释放。

更改mapType似乎释放mapview所持有的内存。 因此,请尝试在mapviewcontroller中的mapview对象发布之前重置mapType。 在语句执行之后,您可以看到内存正在closures。

 - (void)dealloc { // this is a trick for releasing memory __mapView.mapType = MKMapTypeStandard; [__mapView removeFromSuperview]; __mapView.delegate = nil; [__mapview release]; [super dealloc]; } 

希望能帮助到你。