UIWebView leaking memory when loading .RTF files? - iphone

Trying to load a .rtf file (2.4 MB) via webView like this:
NSURL *docURL = [NSURL fileURLWithPath:docPath];
NSData *data = [NSData dataWithContentsOfURL:docURL];
NSString *mimeType = //receiving proper mime type here
[webView loadData:data MIMEType:mimeType textEncodingName:#"utf-8" baseURL:docURL];
Loading such files leads to memory growth until app crashes. According to the Instruments memory growth continues even after complete deallocation of webView containing controller and webView itself. Being in other place of the application, using other app features, memory grows as if I'm still continuing browsing that .RTF file.
When closing/dismissing the controller I also do all things to deallocate WebView.
That is: mainWebview.delegate = nil; [mainWebview stopLoading]; , [mainWebview removeFromSuperview]; , [mainWebview release]; .
(Even tried to do the following: [mainWebview loadHTMLString:#"" baseURL:nil]; )
What I see in instruments:
Does anybody have any ideas?
Thanks.
EDIT: I tested some large .RTF files (700 Kb - 2.4 Mb) on Safari, Chrome, Mercury browsers. Same thing happens everywhere, both simulator and device. I guess it's some bug in WebKit.
General situation: browsers use too much memory to process this kind of files. In 90% of cases just abnormally exit with "Crash" or "Low Memory" signal. If device handles peak memory usage when loading the file then memory drains back to normal, if not - it crashes.

I have also had several issues related to memory management when using UIWebView. In my case, I saw that behavior changed a lot depending on the way I loaded data into the web view. In your case, I have no solution, but based on my experience, maybe using:
NSURLRequest *req = [NSURLRequest requestWithURL:urlToYourRTFFile];
[webView loadRequest:req];
could make a difference

Related

detect no disk space iPhone SDK

Suppose I need to write many images to iPhone file system. And I need to find I have enough space to write image to disk. Is it possible using iPhone SDK?
Yes, it is possible. See the following tutorial (found using the powerful "google" search engine) ;)
http://iphoneincubator.com/blog/device-information/how-to-obtain-total-and-available-disk-space-on-your-iphone-or-ipod-touch
Edit: added response re: writing UIImage to disk, with unknown available disk space:
Try-Catch a bad way of doing things. Exceptions in cocoa are only for truly exceptionally circumstances (i.e. crash-worthy). If you write your image using
NSData *imageData = [myImage UIImageJPEGRepresentation];
(or UIImagePNGRepresentation)
and then
NSError *error;
BOOL success = [imageData writeToFile:(NSString *)path options:(NSDataWritingOptions)mask error:&error];
Your BOOL failed will tell you if it worked, and error will contain an NSError object with a description of the error (don't test for error != nil though, that'll crash occasionally).

UIDocumentInteractionController crashes on device for large images

I use UIDocumentInteractionController for quick look on iPad (4.3.3).
NSURL *url = [NSURL fileURLWithPath:path];
self.doc = [UIDocumentInteractionController interactionControllerWithURL:url];
self.doc.delegate = self;
[self.doc presentPreviewAnimated:YES];
This works fine for all supported types and for jpg images up to (~ 2000x2000 px). Then I tried to quick view jpg image 6000x6000 px and got a crash with message:
[Switching to process 11779 thread 0x0]
warning: Unable to read symbols for /Developer/Platforms/iPhoneOS.platform/DeviceSupport/4.3.3 (8J3)/Symbols/System/Library/Frameworks/QuickLook.framework/DisplayBundles/Image.qldisplay/Image (file not found).
warning: No copy of Image.qldisplay/Image found locally, reading from memory on remote device. This may slow down the debug session.
Large images on emulator work fine. Quicklook.framework is in Build Phase. What's the reason?
Large Image size = 426Kb (compressed jpeg).
UPD: same story on iPad2
UPD2: I tried to use UIWebView instead, no crashes but no an ideal solution
UIDocumentInteractionController crashes frequently with files of moderate size. As you are on 4.3.3, you could try the QLPreviewController.

Loading performance between a UIWebView and Safari is considerably different, any pointers?

I have a UIWebView in an iPhone application I am building. It's job is to load up a URL. The code I use is:
NSURL *url = [NSURL URLWithString:providedURL];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[webView loadRequest:request];
This is in viewDidLoad.
I have noticed that it takes around 18 seconds for the page to load in my app....but when using Safari it takes 5-8 seconds. Has anyone run into this issue before? Does it have anything to do with how I'm forming my request?
It is likely because Safari has cached the resources of the site already. A basic UIWebView does not do any caching by itself. You'll have to implement that yourself. See a question about that here:
How to cache content in UIWebView for faster loading later on?

iPhone Dev: big png sequences cause crash?

I'm building an app which includes a number of image sequences (5 sequences with about 80 images each). It runs nicely in the iPhone simulator, but causes my iPhone to reboot when I test it. By the way, each png image is about 8k in size.
Has anyone successfully built a similar app?
Am I using too many resources for the iPhone to handle?
Anyone?
UPDATE:
Thanks to all for you answers! I've modified my code to use [UIImage imageWithContentsOfFile:] instead of [UIImage imageNamed:]
However I'm still unable to prevent the app from crashing my iPhone.
(please note that my pngs are not that big about 400x400px / 8k)
Does anyone have any suggestions?
Here's my code:
// code snippet:
myFrames = [[NSMutableArray alloc] initWithCapacity:maxFrames];
NSMutableString *curFrame;
num = 0;
// loop (maxframes = 80)
for(int f = 1; f < maxFrames+1; f++)
{
curFrame = [NSMutableString stringWithString:tName];
if(f < 10) [curFrame appendString:[NSString stringWithFormat:#"00%i",f]];
else if(f>9 && f<100) [curFrame appendString:[NSString stringWithFormat:#"0%i",f]];
else [curFrame appendString:[NSString stringWithFormat:#"%i",f]];
UIImage *img = [UIImage imageWithContentsOfFile: [[NSBundle mainBundle] pathForResource:curFrame ofType:#"png"]];
if(img) [myFrames addObject:img];
[img release];
}
// animate the images!
self.animationImages = myFrames;
self.animationDuration = (maxFrames * .05); // Seconds
[self startAnimating];
The best way to find out is to run the application under Instruments using Leaks or Object Alloc. If you see an upward trend that keeps rising, you might have a leak.
If you're using [UIImage imageNamed:], you should be aware that it pre-caches an optimized version which takes up more memory when compared with [UIImage imageWithContentsOfFile:]. Additionally, until iPhone 3.0, the cache created by [UIImage imageNamed:] doesn't get released when there's a memory warning.
The current-gen iPhone only has 128MB of ram, some of which is used by the OS itself. A 320x480 image fully uncompressed with an alpha channel can take 614k. If you have 400 unique images that are full screen, that's well over 128MB of ram, assuming it is loaded up and cached uncompressed.
The number one reason why an app would not crash on the simulator but on the phone would be memory
On the iphone simulator AFAIK the memory is not limited to 128Mb while on the iphone once it reaches 128Mb it restarts. So check your memory usage on the simulator. You have to change the way you are loading the images and or check for leaks. Also check if your getting low memory warnings by implementing the methods (I forgot what they are called :()
I've seen apps run in the simulator and not on the phone because of improper PNG formatting (even a single improperly formatted image can cause this crash). Check to make sure that the format of your images matches those of PNG files provided by apple in their example apps.
That being said 400 full screen images would easily cause it to run out of memory as in memory they will occupy far more than the 8kb. Not sure how big those images are, but if they're all in memory they will need to be very, very small on the iPhone.
The first answer to your question states that while your PNGs may take up only 8K on disk, that is the compressed on-disk form. When it is loaded into memory, it is decompressed and is much larger than 8K. At 32-bits per pixel, a 400x400 image will be 640K.
Even without the alpha channel, you're looking at 480K. 480K x 80 frames, that is 38.4MB, which is definitely creeping into using more memory than the iphone has available to give your app at once. Here is an article about some of the troubles with obtaining a substantial about of memory from the iPhone OS.

How does the default Camera iPhone app manages to save a photo so fast?

So far I've managed to create an app for iPhone that takes multiple images with about a 3 second interval between each. I`m processing each image in a separate thread asynchronously and everything is great till it gets to the moment for saving the image on the iPhone disk. Then it takes about 12 seconds to save the image to the disk using JPEG representation.
How does Apple do it, how do they manage to save a single image so fast to the disk is there a trick they are using? I saw that the animations distract the user for a while, but still the time needed is below 12 seconds!
Thanks in advance.
Actually apple uses its kernal driver AppleJPEGDriver, It is a hardware jpeg encoding api and is much faster than software encoding (JPEGRepresnetaion) and some of the people using it in their jailbreak apps(cycorder video recording application).
Apple should give the same functionality to its users but they are apple :)
I haven't tried this but I wouldn't be so sure that Apple isn't using the same methods. A big part of the Apple design philosophy relies on hiding operational interruptions from the user. The Apple code may take as much time as yours but simply be adroit at hiding the entire save time from the perception of the user.
If someone can't tell you how Apple actually does save faster I would suggest looking at ways to disguise the save time.
If you google around a bit... there is a whole bunch of people with the same problem.
I didn't find an answer. The general conclusion seems to be that apple either uses some internal api and bypass public api overhead or some hardware encoder.
Guess you are out of luck for fast image saving
I was having this problem in my app, on saving it would hang so I used Grand central dispatch.
Below is the setImage method out of my image cache class, if UIImage has a image it saves it otherwise it deletes it. You can adapt this to suit your needs hopefully, will only work on iOS 4+. The code is ARC enabled.
-(void)setImage:(UIImage *)image{
if (image == nil){
NSLog(#"Deleting Image");
// Since we have no image let's remove the cached image if it exists
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSString *cachePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory,
NSUserDomainMask, YES) objectAtIndex:0];
[[NSFileManager defaultManager] removeItemAtPath:[cachePath
stringByAppendingPathComponent:#"capturedimage.jpg"] error:nil];
});
}
else {
NSLog(#"Saving Image");
// We've got an image, let's save it to flash memory.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSString *cachePath =
[NSSearchPathForDirectoriesInDomains(NSCachesDirectory,
NSUserDomainMask, YES) objectAtIndex:0];
NSData *dataObj = UIImagePNGRepresentation(image);
[dataObj writeToFile:[cachePath
stringByAppendingPathComponent:#"capturedimage.jpg"] atomically:NO];
});
}
imageCache = image;
}