iPhone Instruments Leaks 让我很困惑。 UIView 淡出动画导致大量微小泄漏
我正在尝试消除 iPhone 3.0 应用程序中的所有内存泄漏。 CLANG 构建时所有灯均为绿色,因此现在我正在使用 Instruments 进行分析。
这说起来容易做起来难,因为在使用该应用程序几分钟后就表明存在数百个 16 字节泄漏。它似乎主要在 UIKit 中,共同的部分是堆栈跟踪的末尾总是调用 [NSObject respondsToSelector]
这是我可以忽略的东西还是所有这些泄漏的原因是什么? 我可以忽略它们,有没有办法在仪器中过滤掉它们,这样我就可以检测到真正的泄漏?
*编辑 我设法找到了导致问题的代码部分,但我仍然不明白为什么。 我有一个自定义 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
I'm trying to kill all memory leaks in my iPhone 3.0 application. CLANG builds with all lights green so now I'm analyzing with Instruments.
This is easier said then done, since it is indicating hundreds of 16 byte leaks after just a few minutes of using the app. It seams to be mainly in UIKit, and the common part is that the end of the stack trace always calls [NSObject respondsToSelector]
Is this something I can ignore or what can be the reason for all these leaks?
I I can ignore them, is there a way to filter them out in Instruments, so I can detect the real leaks?
*EDIT
I managed to find the part of my code that caused the problem, but I still don't understand why.
I have a custom UIView with some text and a spinner that is visible during an async http request. When the request is done I call this method on the view:
- (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];
}
If I instead simply do
[self removeFromSuperView]
without the alpha animation, there is no leaks reported.
See the screenshot below for Instruments details.
A sample stack trace:
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
And another one:
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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您没有指定是否在实际设备上对模拟器进行了检查,但根据我的经验,在模拟器中运行 Leaks 不是很可靠,并且会报告 SDK 中的许多微小泄漏,而在设备上运行它则不会报告任何泄漏。
You didn't specify if you did your checks on the simulator on an actual device, but in my experience running Leaks in the simulator is not very reliable and will report many tiny leaks in the the SDK, while running it on the device will not report any leaks.
您确定正在调用您的委托方法吗?我认为问题在于动画委托方法,根据苹果的文档,该方法必须具有以下签名:
然后你的类中有一个这样的方法:
也许你的动画委托没有被调用,因此,该对象没有被释放。
从文档中:
希望这有帮助!
Are you sure your delegate method is being called? I think the problem is the animation delegate method, which, according to Apple's documentation, must have this signature:
And then you have a method like this in your class:
Probably your animation delegate is not being called, thus, the object is not released.
From the documentation:
Hope this helps!