iPhone Instruments Leaks is confusing me. UIView fade out animation causes a lot of tiny leaks
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.
Instruments Screenshot
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
开发者_C百科 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
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:
[UIView setAnimationDidStopSelector:@selector(animationFinished:finished:context:)];
And then you have a method like this in your class:
#pragma mark -
#pragma mark UIView animation delegate method
- (void)animationFinished:(NSString *)animationID
finished:(BOOL)finished
context:(void *)context
{
[self removeFromSuperview];
}
Probably your animation delegate is not being called, thus, the object is not released.
From the documentation:
setAnimationDidStopSelector:
Sets the message to send to the animation delegate when animation stops.
- (void)setAnimationDidStopSelector:(SEL)selector
Parameters
selector
The message sent to the animation delegate after animations end. The default value is NULL. The selector should be of the form: - (void)animationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context. Your method must take the following arguments:
animationID
An NSString containing an optional application-supplied identifier. This is the identifier that is passed to the beginAnimations:context: method. This argument can be nil.
finished An NSNumber object containing a Boolean value. The value is YES if the animation ran to completion before it stopped or NO if it did not.
context
An optional application-supplied context. This is the context data passed to the beginAnimations:context: method. This argument can be nil.
Hope this helps!
精彩评论