Adam Swinden
Adam Swinden

Reputation: 1916

Images not loading in a UIWebView using symbolic links in the Documents directory linked to the bundle?

I am loading a UIWebView using [myWebView loadHTMLString:htmlString baseURL:documentsDirectoryURL] with a local NSString of HTML and a baseURL of a directory in the app's Documents directory.

The problem is that the HTML contains <img> tags with images that are loaded from the above directory. Instead of the directory in the Documents directory containing the images, it contains symlinks to images contained in the app bundle.

When the UIWebView is loaded on first launch the images fail to load resulting in the standard Safari blue question marks. If I then quit the app, relaunch and load the UIWebView again the images load fine.

Has anyone else had this problem?

The symbolic links are created like this:

- (void)createSymbolicLinksForURL:(NSURL *)url inDirectory:(NSURL *)directory {

    NSFileManager *fileManager = [NSFileManager defaultManager];

    NSDirectoryEnumerator *dirEnum = [fileManager enumeratorAtURL:url
                                       includingPropertiesForKeys:[NSArray arrayWithObject:NSURLIsDirectoryKey] 
                                                          options:NSDirectoryEnumerationSkipsHiddenFiles | NSDirectoryEnumerationSkipsPackageDescendants
                                                     errorHandler:nil];

    NSArray *resourceKeys = [NSArray arrayWithObjects:NSURLIsSymbolicLinkKey, NSURLIsDirectoryKey, nil];

    for (NSURL *bundledURL in dirEnum) {

        if ([[[bundledURL resourceValuesForKeys:resourceKeys error:nil] objectForKey:NSURLIsDirectoryKey] boolValue]) continue;

        NSArray *bundledURLPathComponents = [bundledURL pathComponents];

        NSURL *destinationURL = directory;

        for (NSUInteger componentIndex = [bundledURLPathComponents count] - dirEnum.level; componentIndex < [bundledURLPathComponents count]; componentIndex++) {

            destinationURL = [destinationURL URLByAppendingPathComponent:[bundledURLPathComponents objectAtIndex:componentIndex]];
        }

        if ([fileManager fileExistsAtPath:destinationURL.path]) {

            if ([[[destinationURL resourceValuesForKeys:resourceKeys error:nil] objectForKey:NSURLIsSymbolicLinkKey] boolValue]) {

                [fileManager removeItemAtURL:destinationURL error:nil];
            }
            else {

                continue;
            }
        }

        NSURL *container = [destinationURL URLByDeletingLastPathComponent];
        if (![fileManager fileExistsAtPath:container.path]) [fileManager createDirectoryAtURL:container withIntermediateDirectories:YES attributes:nil error:nil];

        NSError *error = nil;
        [fileManager createSymbolicLinkAtURL:destinationURL withDestinationURL:bundledURL error:&error];
        if (error) NSLog(@"Failed to create symbolic link for %@ (Error: %@)", bundledURL, error);
    }
}

The HTML string that is loaded by the UIWebView looks like this (this is just a snippet):

<img src="images/thumb.jpg">
<img src="images/thumb1.jpg">
<img src="images/thumb2.jpg">

Resulting in this on the first launch:

First launch

...and this on any subsequent launches:

Subsequent launch

Upvotes: 0

Views: 1089

Answers (1)

Adam Swinden
Adam Swinden

Reputation: 1916

It seems that moving the symbolic links into the root of the Documents directory and therefore shortening the <img> tags to <img src="thumb.jpg">, for example, fixed the problem - the images loaded on first launch.

This was not sufficient enough of a solution as I really needed to group resources into directories inside the Documents directory. So I instead tried extending the <img> tags to include absolute URLs to the symbolic links. For example (when running in the simulator):

<img src="file://localhost/Users/adam/Library/Application%20Support/iPhone%20Simulator/5.1/Applications/677CFABC-D16A-42C8-8F08-6FF415522FB6/Documents/images/thumb.jpg">

..and it works!

Thanks to S P Varma for the tip!

Upvotes: 2

Related Questions