弹出UIViewController后,MKMapView自动释放不调用dealloc

时间:2014-01-14 21:29:56

标签: ios objective-c memory-management memory-leaks uiviewcontroller

我在A类中有以下代码:

UIViewController *vc = [self viewControllerForItem:item];

其中我的app委托中的viewControllerForItem方法返回基于我的项目的UIViewController,即

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

return vc;
然后我按下视图控制器:

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

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

但是,当我按下VC后添加以下代码时:

[vc release];

我的MKMapView类调用dealloc方法。

当然,如果MKMapView类是我的app委托返回的唯一类(或者我可以检查VC的类是否是我的MKMapView类),这将是一个简单的解决方案。但是,我想解决这个根本问题。

  1. 如果我在视图控制器上设置autorelease,为什么不调用dealloc?

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

  3. 由于

    编辑:

    这是一些额外的信息。我的app委托中有viewControllerForItem类。我将自动释放的对象返回到我的其他管理器类中,然后我按下视图控制器。当我返回一个自动释放的对象时,保留计数是否被搞砸了,然后将其推送到其他类中?

    当我推送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
    )
    

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

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

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

2 个答案:

答案 0 :(得分:8)

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

  • 在Xcode中,从菜单中选择“产品>配置文件”。

  • 当仪器启动时,选择“分配”模板。

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

  • 单击分配工具上的“i”按钮,然后选中“记录参考计数”。

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

  • 点击“录制”按钮启动您的应用,等待您的应用在模拟器中启动。

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

  • 在仪器中,单击“暂停”按钮

  • 使用窗口右上角的搜索字段搜索CustomAdvancedGPSMapViewController。 CustomAdvancedGPSMapViewController应出现在“分配摘要”列表中。

  • 在“分配摘要”列表中,点击 - > CustomAdvancedGPSMapViewController名称旁边的箭头。这应该表明您的应用程序中有一个CustomAdvancedGPSMapViewController实例。

  • 点击 - >地址旁边的箭头。这将显示此CustomAdvancedGPSMapViewController实例的保留/发布历史记录。

  • 取消暂停仪器,返回模拟器,关闭CustomAdvancedGPSMapViewController并返回到您认为应该取消分配控制器的位置。

  • 返回“工具”,再次单击“暂停”,查看更新的保留/发布历史记录。

保留/释放历史记录中的第一个事件应为“malloc”。选择此行,窗口右侧的“扩展详细信息”视图将显示此分配的堆栈跟踪。您应该在堆栈跟踪中看到自己的代码。双击堆栈跟踪中的代码,您应该看到分配了CustomAdvancedGPSMapViewController实例的代码行。

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

保留/发布历史记录中的最后一个事件应该是“免费”的。如果不是这种情况可能会发生泄漏。检查保留/释放历史记录并查找无与伦比的保留。可能存在很多与CoreAnimation相关的噪声等。查找代码出现在堆栈跟踪中的事件。

将保留/释放历史记录与未泄漏的其他视图控制器进行比较。

如果CustomAdvancedGPSMapViewController没有泄露,请尝试检查MKMapView的历史记录。

答案 1 :(得分:2)

您编写的代码是正确的,您不应该发布vc,因为它已经自动释放了。

-(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即使在发布后也没有释放内存的问题。它似乎是一个苹果bug,只有当你获得mapview的内存警告时,这个内存才会被销毁。但你可以通过破解来强制释放。

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

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

希望它有所帮助。