ChatGPT解决这个技术问题 Extra ChatGPT

Load resources from relative path using local html in uiwebview

I have a very simple iOS app with a uiwebview loading a very simple test page (test.html):

<html>
<body>
<img src="img/myimage.png" />
</body>
</html>

I load this test.html file into my web view:

NSURL *url = [[NSBundle mainBundle] URLForResource:@"test" withExtension:@"html"];
NSString *html = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:nil];
NSURL *baseUrl = [NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]];
[webView loadHTMLString:html baseURL:baseUrl];

This works fine if I reference the image without the relative path and put the referenced image in the root path under Targets -> Copy Bundle Resources within XCode, however I can't get it to work with the relative path as shown in my html file. There must be a way to do this, I have lots of images, css, javascript files that I want to load into the webview and I would like not to have to have everything in the root and have to change all the references in my web app.


c
clozach

This is how to load/use a local html with relative references.

Drag the resource into your xcode project (I dragged a folder named www from my finder window), you will get two options "create groups for any added folders" and "create folders references for any added folders". Select the "create folder references.." option. Use the below given code. It should work like a charm. NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"index" ofType:@"html" inDirectory:@"www"]]; [webview loadRequest:[NSURLRequest requestWithURL:url]];

Now all your relative links(like img/.gif, js/.js) in the html should get resolved.

Swift 3

    if let path = Bundle.main.path(forResource: "dados", ofType: "html", inDirectory: "root") {
        webView.load( URLRequest(url: URL(fileURLWithPath: path)) )
    }

Super and Up voted! Can anyone explain why "create folder references as oppose to "create groups for any added folders"?
As a sidenote, if you are trying to load javascript files as opposed to images, you'll need to look at this as well: stackoverflow.com/a/3629479/385619
What if the directory is n folders deep? Is it okay to pass a string like @"www/app" for the directory arg?
What if we load the html from the Documents, not from the Bundle?
@Sean XCode by default stores all files added in the root folder, groups are only for making your project tree look good. Folder references actually copy contents as-is, preserving the directory structure. That's pretty essential if you want your relative paths to work on device the same way they do on your office machine.
A
Ahmad

In Swift:

 func pathForResource(  name: String?, 
                        ofType ext: String?, 
                        inDirectory subpath: String?) -> String?  {

  // **name:** Name of Hmtl
  // **ofType ext:** extension for type of file. In this case "html"
  // **inDirectory subpath:** the folder where are the file. 
  //    In this case the file is in root folder

    let path = NSBundle.mainBundle().pathForResource(             "dados",
                                                     ofType:      "html", 
                                                     inDirectory: "root")
    var requestURL = NSURL(string:path!)
    var request = NSURLRequest(URL:requestURL)

    webView.loadRequest(request)
}

Thanks for the Swift code. Worked well along with the Accepted Answer
Welcome! :.) @Bala Vishnu
Works great, I had to unwrap the requestURL though.
P
PengOne

I crammed everything into one line (bad I know) and had no troubles with it:

[webView loadRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"test" 
                                                                                                         ofType:@"html"]
                                                             isDirectory:NO]]];         

In the XCode project for your image under the targets node do you use "Relative to project" or "Relative to Enclosing Group"? I was using Relative to project because in the get info dialog the path it shows when I choose Relative to project looks correct. However it appears to load the image correctly when I choose relative to enclosing group. Now I've just go to get my full page to work correctly with javascript and css and all, thanks!
Ugh! This uiwebview is so fragile, I started slowly adding more complex tests to my test page (i.e. setting the image with css instead of inline in the img tag) and it wasn't working so I reverted back to what I had originally and it didn't work again! Maybe I'm dealing with some sort of caching in my uiwebview?
O
Old McStopher

I simply do this:

    UIWebView *webView = [[[UIWebView alloc] init] autorelease];

    NSURL *url = [[NSBundle mainBundle] URLForResource:@"index" withExtension:@"html"];
    NSURLRequest* request = [NSURLRequest requestWithURL:url];
    [webView loadRequest:request];

Where "index.html" relatively references images, CSS, javascript, etc.


f
fishinear

Swift answer 2.

The UIWebView Class Reference advises against using webView.loadRequest(request):

Don’t use this method to load local HTML files; instead, use loadHTMLString:baseURL:.

In this solution, the html is read into a string. The html's url is used to work out the path, and passes that as a base url.

let url = bundle.URLForResource("index", withExtension: "html", subdirectory: "htmlFileFolder")
let html = try String(contentsOfURL: url)
let base = url.URLByDeletingLastPathComponent
webView.loadHTMLString(html, baseURL: base)

If this is the case, it would be good to refer to where in the manual it advises this and insert an excerpt from that page - it seems very much without context at the moment.
Apple's comment is on the Instance Method page for loadRequest:
M
Matt Palmerlee

I've gone back and tested and re-tested this, it appears that the only way I can get it to work (since I have some files in the img folder and some in js/css, etc...) is not to use a relative path to my image in the html and have everything referenced to the bundle folder. What a shame :(.

<img src="myimage.png" />

s
skornos

@sdbrain's answer in Swift 3:

    let url = URL.init(fileURLWithPath: Bundle.main.path(forResource: "index", ofType: "html", inDirectory: "www")!)
    webView.loadRequest(NSURLRequest.init(url: url) as URLRequest)

B
Bently Bobo

In Swift 3.01 using WKWebView:

let localURL = URL.init(fileURLWithPath: Bundle.main.path(forResource: "index", ofType: "html", inDirectory: "CWP")!)
myWebView.load(NSURLRequest.init(url: localURL) as URLRequest)

This adjusts for some of the finer syntax changes in 3.01 and keeps the directory structure in place so you can embed related HTML files.


Wasn't the NS prefix dropped out for the key foundation types since 3.x? That did the trick for me, thanks! let localURL = URL.init(fileURLWithPath: Bundle.main.path(forResource: "index", ofType: "html", inDirectory: "mapa_procesos")!) webView.loadRequest(URLRequest(url: localURL))

关注公众号,不定期副业成功案例分享
Follow WeChat

Success story sharing

Want to stay one step ahead of the latest teleworks?

Subscribe Now