1

我正在尝试消除我的 iPhone 3.0 应用程序中的所有内存泄漏。CLANG 构建时所有灯都是绿色的,所以现在我正在使用 Instruments 进行分析。

这说起来容易做起来难,因为它表明在使用该应用程序几分钟后就有数百个 16 字节泄漏。它似乎主要在 UIKit 中,共同的部分是堆栈跟踪的末尾总是调用[NSObject respondsToSelector]

这是我可以忽略的事情还是所有这些泄漏的原因是什么?II 可以忽略它们,有没有办法在 Instruments 中将它们过滤掉,这样我就可以检测到真正的泄漏?

*编辑我设法找到导致问题的代码部分,但我仍然不明白为什么。我有一个带有一些文本的自定义 UIView 和一个在异步 http 请求期间可见的微调器。请求完成后,我在视图上调用此方法:

- (void)fadeOut{
    spinner.hidden = YES;
    loadingLabel.hidden = YES;
    messageLabel.hidden = YES;
    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationDelegate:self];
    [UIView setAnimationDidStopSelector:@selector(fadeComplete)];
        [UIView setAnimationDuration:0.40];
    self.alpha = 0.0;
        [UIView commitAnimations];
}

- (void)fadeComplete{
    [self removeFromSuperview];
}

如果我只是简单地做

[self removeFromSuperView]如果没有 alpha 动画,则不会报告泄漏。

有关仪器的详细信息,请参见下面的屏幕截图。

仪器截图

示例堆栈跟踪:

   0 libobjc.A.dylib _malloc_internal
   1 libobjc.A.dylib _cache_addForwardEntry
   2 libobjc.A.dylib lookUpMethod
   3 libobjc.A.dylib class_respondsToSelector
   4 CoreFoundation -[NSObject respondsToSelector:]
   5 UIKit -[UINavigationTransitionView transition:fromView:toView:]
   6 UIKit -[UINavigationTransitionView transition:toView:]
   7 UIKit -[UINavigationController _startTransition:fromViewController:toViewController:]
   8 UIKit -[UINavigationController _startDeferredTransitionIfNeeded]
   9 UIKit -[UINavigationController viewWillLayoutSubviews]
  10 UIKit -[UILayoutContainerView layoutSubviews]
  11 UIKit -[UIView(CALayerDelegate) _layoutSublayersOfLayer:]
  12 QuartzCore -[CALayer layoutSublayers]
  13 QuartzCore CALayerLayoutIfNeeded
  14 QuartzCore CA::Context::commit_transaction(CA::Transaction*)
  15 QuartzCore CA::Transaction::commit()
  16 QuartzCore CA::Transaction::observer_callback(__CFRunLoopObserver*, unsigned long, void*)
  17 CoreFoundation __CFRunLoopDoObservers
  18 CoreFoundation CFRunLoopRunSpecific
  19 CoreFoundation CFRunLoopRunInMode
  20 GraphicsServices GSEventRunModal
  21 GraphicsServices GSEventRun
  22 UIKit -[UIApplication _run]
  23 UIKit UIApplicationMain
  24 Client main **/main.m:14
  25 Client start

还有一个:

   0 libobjc.A.dylib _malloc_internal
   1 libobjc.A.dylib _cache_addForwardEntry
   2 libobjc.A.dylib lookUpMethod
   3 libobjc.A.dylib class_respondsToSelector
   4 CoreFoundation -[NSObject respondsToSelector:]
   5 UIKit -[UIViewAnimationState animationDidStart:]
   6 QuartzCore run_animation_callbacks(double, void*)
   7 QuartzCore CA::timer_callback(__CFRunLoopTimer*, void*)
   8 CoreFoundation CFRunLoopRunSpecific
   9 CoreFoundation CFRunLoopRunInMode
  10 GraphicsServices GSEventRunModal
  11 GraphicsServices GSEventRun
  12 UIKit -[UIApplication _run]
  13 UIKit UIApplicationMain
  14 Client main ***/main.m:14
  15 Client start
4

2 回答 2

3

您没有指定是否在实际设备上对模拟器进行了检查,但根据我的经验,在模拟器中运行 Leaks 不是很可靠,并且会在 SDK 中报告许多微小的泄漏,而在设备上运行它不会报告任何泄漏。

于 2010-01-08T03:24:12.873 回答
1

你确定你的委托方法被调用了吗?我认为问题在于动画委托方法,根据Apple的文档,它必须具有以下签名:

[UIView setAnimationDidStopSelector:@selector(animationFinished:finished:context:)];

然后你的类中有一个这样的方法:

#pragma mark -
#pragma mark UIView animation delegate method

- (void)animationFinished:(NSString *)animationID 
                 finished:(BOOL)finished 
                  context:(void *)context
{
    [self removeFromSuperview];
}

可能您的动画委托没有被调用,因此,该对象没有被释放。

从文档中:

setAnimationDidStopSelector:

设置动画停止时发送给动画代理的消息。

  • (void)setAnimationDidStopSelector:(SEL)选择器

参数

选择器

动画结束后发送给动画代理的消息。默认值为 NULL。选择器应采用以下形式:- (void)animationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context。您的方法必须采用以下参数:

动画ID

一个 NSString 包含一个可选的应用程序提供的标识符。这是传递给 beginAnimations:context: 方法的标识符。这个参数可以为零。

一个包含布尔值的 NSNumber 对象。如果动画在停止之前完成,则值为 YES,否则为 NO。

语境

一个可选的应用程序提供的上下文。这是传递给 beginAnimations:context: 方法的上下文数据。这个参数可以为零。

希望这可以帮助!

于 2010-01-06T07:29:22.110 回答