massive memory leak in ios UIWebView - ios

looking for mem leaks elsewhere in our system, I created a 20 MB web page with a meta refresh tag. the idea was to move a lot data through our datapath code to confirm mem stability.
<html>
<meta http-equiv="refresh" content="1">
<body>
<div style="border: 1px solid red">
Content loading
</div><!-- 20mb worth of comments -->
</body>
</html>
what I found was the uiwebview displaying that meta refresh page leaks memory very, very fast. the app memory hits 300mb in about 2 minutes and gets shot on a low mem warning, even when our code is not in play.
I have stopped the refresh loading and tried to dealloc the webview.
I have tried loadurl:"about:blank", loadhtml:"", javascript document close.
I also tried writing a recursive removeFromSuperview and removeFromParentViewController, reading that the private scrollview in the webview is a memory problem, but that memory is never freed. I can't seem to find a reliable way to close, dealloc a webview when we are done with it.
We have lived with a slow rate of webview leaking for quite a while and really want to find a way of assuring a webview can be fully cleaned up when we are done with it. We recently converted the app to ARC which did not change the memory rate.
I am considering trying a recursive loop through all the objects in the webview and see if they can be freed. instruments shows 20 mb of cfdatas, alive, for each refresh of the 20MB page, but does not show them as leaks. if i only deliver the response header and done to the urlprotocol client we run stably so was ale to confirm the memleaks in the rest of the data path, but this is such a dramatic test case result am hoping to find a webview mem leak solution once and for all.
Does any one have any better ideas or has anyone tried recursing through the objects in a uiwebview?

The way I got rid of my UIWebView's memory leakage is by setting its HTML to the empty string. One place to do this is when the view controller containing the web view disappears:
- (void) viewWillDisappear:(BOOL)animated {
if (self.isMovingFromParentViewController) {
[self.wv loadHTMLString: #"" baseURL: nil];
}
}

A shout to all developers: Implementing didReceiveMemoryWarning is an absolute must when using a UIWebView!
And it's specially important when the UIWebView can navigate anywhere or to a page you know that causes UIWebView to have huge leaks, such as m.youtube.com.
A great and usually seamless way to fix the leaks is just reloading the page. In that way you don't need to care about the page becoming empty, and usually the user will be able to continue its work from where he left off.
In your view controller, override didReceiveMemoryWarning like this:
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
[myWebView reload];
}

With iOS 8 and onwards, you are really in luck. WKWebView does not leak and has a much smaller memory footprint than UIWebView. Having tested it with image laden web pages containing complex Javascript, it performed well.
Apple's WKWebView Class Reference
nshipster on WKWebView
It's not perfect though. Then again hopefully imperfections will be resolved in time. Check out Shingo Fukuyama's tips on GitHub:
WKWebViewTips

Weakify "self" in the blocks.
This was one of the important reasons that lead to holding up of WebView memory even when popped out the navigation stack.

Related

SpriteKit Memory Leak on static Menu scene

Im experiencing memory leak on static menu scene, it appears that it happens on every scene, game scene itself but also static menu/gameover. Memory appears to be deallocated correctly (and it's reduced when scene is gone).
Those static scenes does not conatins even update callback defined.
It's all setup in didMoveToView and inside it there are couple SKLabelNodes and SKSpriteNode allocated with spriteNodeWithImage.
I have tried to use dealloc to monitor if scene got's deallocated correctly, and it appears to be so it seems it's not the source of the issue.
Browsing google pointed me to some other threads created on stackoverflow that
spriteNodeWithImage
textureWithImage
May cause
-Memory leaks
-weird error "CUICatalog: Invalid Request: requesting subtype without specifying idiom"
So i have tried to create UIImage imageNamed and then put in into texture and use in SKTexture, actually it has removed CUICatalog error (which anyway, seems like a stupid message which did not been removed by apple - can anyone confirm that ?)
But according to memory leaks this didn't help at all, and anyway anything in that scene is being created once on beginning so i have no idea why this memory keeps growing and growing like 0,5mb per sec.
Looking forward for any tips.
Best regards
Actually i have found the source of the problem.
It seems debugging physics makes huge memory leak
skView.showsPhysics = YES;
It's not a big problem since it happens while debugging only when showsPhysics=YES.
But good to know anyway.

Release memory after a webView [duplicate]

looking for mem leaks elsewhere in our system, I created a 20 MB web page with a meta refresh tag. the idea was to move a lot data through our datapath code to confirm mem stability.
<html>
<meta http-equiv="refresh" content="1">
<body>
<div style="border: 1px solid red">
Content loading
</div><!-- 20mb worth of comments -->
</body>
</html>
what I found was the uiwebview displaying that meta refresh page leaks memory very, very fast. the app memory hits 300mb in about 2 minutes and gets shot on a low mem warning, even when our code is not in play.
I have stopped the refresh loading and tried to dealloc the webview.
I have tried loadurl:"about:blank", loadhtml:"", javascript document close.
I also tried writing a recursive removeFromSuperview and removeFromParentViewController, reading that the private scrollview in the webview is a memory problem, but that memory is never freed. I can't seem to find a reliable way to close, dealloc a webview when we are done with it.
We have lived with a slow rate of webview leaking for quite a while and really want to find a way of assuring a webview can be fully cleaned up when we are done with it. We recently converted the app to ARC which did not change the memory rate.
I am considering trying a recursive loop through all the objects in the webview and see if they can be freed. instruments shows 20 mb of cfdatas, alive, for each refresh of the 20MB page, but does not show them as leaks. if i only deliver the response header and done to the urlprotocol client we run stably so was ale to confirm the memleaks in the rest of the data path, but this is such a dramatic test case result am hoping to find a webview mem leak solution once and for all.
Does any one have any better ideas or has anyone tried recursing through the objects in a uiwebview?
The way I got rid of my UIWebView's memory leakage is by setting its HTML to the empty string. One place to do this is when the view controller containing the web view disappears:
- (void) viewWillDisappear:(BOOL)animated {
if (self.isMovingFromParentViewController) {
[self.wv loadHTMLString: #"" baseURL: nil];
}
}
A shout to all developers: Implementing didReceiveMemoryWarning is an absolute must when using a UIWebView!
And it's specially important when the UIWebView can navigate anywhere or to a page you know that causes UIWebView to have huge leaks, such as m.youtube.com.
A great and usually seamless way to fix the leaks is just reloading the page. In that way you don't need to care about the page becoming empty, and usually the user will be able to continue its work from where he left off.
In your view controller, override didReceiveMemoryWarning like this:
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
[myWebView reload];
}
With iOS 8 and onwards, you are really in luck. WKWebView does not leak and has a much smaller memory footprint than UIWebView. Having tested it with image laden web pages containing complex Javascript, it performed well.
Apple's WKWebView Class Reference
nshipster on WKWebView
It's not perfect though. Then again hopefully imperfections will be resolved in time. Check out Shingo Fukuyama's tips on GitHub:
WKWebViewTips
Weakify "self" in the blocks.
This was one of the important reasons that lead to holding up of WebView memory even when popped out the navigation stack.

SDWebImage - Memory leak in UITableView?

I'm sorry in advance as maybe this is a dumb and noob question...
I'm using SDWebImage to display pictures in a UITableView in my cellForRowAtIndexPath method, using the classic
[cell.pointPicture setImageWithURL:[NSURL URLWithString:thePoint.imageURL] placeholderImage:[UIImage imageNamed:POINT_DEFAULT_IMAGE]];
(the displayed pictures are light and well compressed jpgs, just some ko, and yes I'm using dequeueReusableCellWithIdentifier of course).
When I inspect my app with "Instrument - Allocations", and just scroll down my UITableView (with 40 cells containing picture, a bit like Instagram), I got a huge amount of memory used ! (see screenshot)
But it seems to be "VM", and especially "VM: CG raster data" from the coreGraphics library.
So the questions are :
Is it normal?
Is that a serious problem?
Is there a way to avoid this?
I'm sorry but after few search on the web I can't find any relevant information concerning the "VM: CG raster data"... Any idea? Thanks in advance !
I experienced the same issue and found the root cause, at least in my implementation.
Root Cause
The root cause was that my table cell stored a strong pointer to the image which is stored in SDWebImage cache. This strong pointer, caused the memory release function of SDWebImage removeAllObjects not to release any memory when receiving a memory warning from iOS.
Solution 1 - Keep weak pointers from within your ViewController and allow only SDWebImage to keep a strong pointer to all UIImage objects.
Solution 2 - Implement - (void)prepareForReuse and set the image pointers to nil
To test this solution run your application and simulate a memory warning - You will be able to see the data removed
I had the same issue. My problem seemed to originate from something else than the SDWebImage cache but since it did contribute to the memory buildup, the first thing I though was that the cache could be the cause of my problem. But it wasn't. It could be you have the same kind of issue. Keep in mind that I am using ARC.
Run the profiler with the Leaks template and check for the allocation of your own classes in the Allocation Summary.
Dive into them and check how they are allocated, if there are leaks. Mind that a leak doesn't show up in the Leaks instrument because you are using ARC. So Instruments could think everything is going oké but there still could be a leak somewhere. By diving in to the allocation of your own classes you could figure out what is going wrong.
Keep in mind that the retain/release count information is only provided when using the Leaks template and not while using the Allocations template.
My problem was that I was referencing instance variables and self directly from within blocks without reassigning them to __weak variables. When self is used within a block it will automatically be retained by ARC and sometimes never released. A weak reference prevents that from happening.
For example, this is wrong:
[[NSNotificationCenter defaultCenter] addObserverForName:UIKeyboardDidShowNotification object:nil queue:nil usingBlock:^(NSNotification *note) {
[self.view setContentOffset:CGPointMake(0.0, kKeyboardOffset) animated:YES];
}];
You should call self using a __weak reference like this:
__weak YourViewControllerClass *weakSelf = self;
[[NSNotificationCenter defaultCenter] addObserverForName:UIKeyboardDidShowNotification object:nil queue:nil usingBlock:^(NSNotification *note) {
[weakSelf.view setContentOffset:CGPointMake(0.0, kKeyboardOffset) animated:YES];
}];
Since my app uses a lot of block's I had a ton of leaks the Leaks instrument could not detect. When I fixed them the memory problem was gone.
I hope this helps.
As explained to me by someone working on SDWebImage :
SDWebImage cache images is using NSCache. It is discardable memory. See Apple documentation, so this is a perfectly normal behavior and the memory is released if needed.
Although NSCache will free memory on low memory system notifications also more critical (and way smaller in memory footprint) objects will get discarded in other parts of the program.
It would be better to set the library's maxMemoryCost (which sets the NSCache totalCostLimit) to a limit to prevent SDWebImage from triggering memory notifications.

webViewDidFinishLoad did finish loading but didn't finish showing content on screen

I'm using webViewDidFinishLoad a lot in my app and there's something about UIWebView that really bugs me, well, actually two things.
The first, when I load new content to a UIWebView I will see for half a second the last page that was loaded to the same UIWebView what will force me to "clean" the UIWebView using something like:
[_mainWebView stringByEvaluatingJavaScriptFromString:#"document.open();document.close();"];
before loading the new content.
The second issue I have and that's the main issue for this question is that if i'll load some new content to my UIWebView and do something like this:
[_mainWebView loadHTMLString:htmlString baseURL:nil];
...
- (void)webViewDidFinishLoad:(UIWebView *)webView {
_mainWebView.alpha = 1;
}
In some cases the UIWebView will show up white for half a second before showing up the content. I'm guessing that the content is already loaded into the UIWebView and that's why webViewDidFinishLoad:webView is firing but for small html pages showing to content takes loner than the actual load. Is there any workaround I can use to avoid the blank screen that is showing for a sec or so but still save that second?
I thought about animating the alpha from 0 to 1 but that solution feels kinda lame to me.
Try adding a javascript callback so you know when the web view contents have actually loaded: Javascript in UIWebView callback to C/Objective-C

Real memory usage - MPFlipTransition

I am creating an app with an UIViewController which displays other UIViewControllers with the MPFlipTransition inside it. It's like a little book on iPad.
The UIViewControllers inside are created each with xibs with 4-5 UIImageViews inside and some of those images are animated with CoreAnimations ([UIView animateWithDuration] blocks)
I remove all the animations in the viewDidDiseappear function with the QuartzCore function removeAllAnimation on each animated layer.
But when I'm testing the app on an iPad 3, it works properly, but on iPad 2 it crashes at about the 8th page change.
I've made a profiling with Instruments and found that the real memory usage was increasing everytime I turned the page (when the MPFlipTransition appears). But even if I remove from the superview the previous views, the real memory usage is not decreasing. I thinks that it created the crash on the iPad 2 because the crash come when the real memory usage is passing the 400 Mbytes value (and the iPad 2 has only 512MB...).
What do you think about this problem ? Any help ? I'm using ARC for memory management...
Thanks for you help ! Feel free to ask if any need of precisions...

Resources