Search code examples
iosobjective-cuiwebviewios-simulatormainbundle

Saving images to Main Bundle and then loading them into HTML works on Simulator, but not on real Device?


I'm trying to preload the image tags from an html string in order to load them when the device is offline. Basically, I strip the source url from all the <img>tags, clean the url to have a clean filename, then download the image.

    __block   NSString *imageName = [[NSString alloc]init];

//Get the string after HTTP://
     NSArray *nohttp = [actualUrl componentsSeparatedByString:@"//"];
    imageName = [nohttp objectAtIndex:1];

//Clean any /.:
    imageName = [imageName stringByReplacingOccurrencesOfString:@"/" withString:@""];
    imageName = [imageName stringByReplacingOccurrencesOfString:@"." withString:@""];
    imageName = [imageName stringByReplacingOccurrencesOfString:@":" withString:@""];
//Add .png at the end as we will be saving it as a PNG
    imageName = [NSString stringWithFormat:@"%@.png", imageName];

//change the source url to the new filename of the image so the WebView will load it from the main bundle
    html = [html stringByReplacingOccurrencesOfString:actualUrl withString:imageName];

//save the image to the main bundle
    NSString *pathString = [NSString stringWithFormat:@"%@/%@",[[NSBundle mainBundle]bundlePath], imageName];

//this just checks if the image already exists                             
    BOOL test = [[NSFileManager defaultManager] fileExistsAtPath:pathString];

     if (!test){

    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul); dispatch_async(queue, ^(void) {

     NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:actualUrl]];
    UIImage* image = [[UIImage alloc] initWithData:imageData];

                                                                                          NSData *imageData2 = UIImagePNGRepresentation(image);
                                                [imageData2 writeToFile:pathString atomically:YES];


    });
 }

Then after I load the html string into the UIWebView, it works perfectly on the simulator, but on the device the images just aren't loaded. Why?

    NSURL *baseUrl = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@",[[NSBundle mainBundle]bundlePath]]];


[self.webView loadHTMLString:self.htmlPage baseURL:baseUrl];

Any suggestions, thoughts? The images download fine on the iOS device/simulator but aren't loaded in the WebView of the real device. It works perfectly for the simulator.


Solution

  • That is correct.

    On iOS an App's bundle is read-only. Any attempts to save changes into your bundle will fail on an iOS device.

    On Mac OS the bundle is not read-only, but you should still treat it as read-only. Modifying your app's bundle is a bad idea. If the user updates their app from the app store, restores from a backup, etc, then changes you save to the bundle will be lost, even on Mac OS.

    The simulator runs under Mac OS, and is built against Mac OS frameworks and the Mac file system.

    There are a fair number of differences between the sim and running on a device. This is one.

    Another example: The iOS file system is always case-senstive. The simulator, which runs on Mac OS, is not case-sensitive by default. (Mac OS can read from volumes running different file systems. The default file system is not case sensitive, but you can set it up to be case-sensitive.)

    The file "Foo.txt" is a different file than the file "foo.txt". They can both exist in the same directory. If your file is called "Foo.txt" and you try to load it with the string "foo.txt" it will fail on an iOS device, but work on Mac OS.

    As a result, you should always test your apps on an actual device. Don't assume that if something works correctly on the sim that it's correct for an iOS device. It may not be.