UIwebview loading remote html with bundle/local images - ios

Well, i searched everywhere but i didn't have any luck with my situation.
I am loading my webpage with UIWebView with the following code:
NSString *fullURL;
fullURL=#"http://domain.com";
NSURL *url=[NSURL URLWithString:fullURL];
NSURLRequest *requestObj=[NSURLRequest requestWithURL:url];
[_webView loadRequest:requestObj];
I want to load the remote HTML file but load the images from the bundle resourses.
The HTML file looks like this:
<img src="http://domain.com/images/image.png" width="20px" height="20px"/>
Can this be done? The majority of the posts over the internet(and here) are for loading local HTML with local images/resources which is different in my case.
Any help with my code?
Thanks

It would probably be better to use some more "loosely coupled" solution - not to edit the HTML code itself in some hacky way (regexp, not regexp... changing the HTML code manually is still pretty hacky).
As a matter of fact, I believe it can be done. The iOS just needs to be somehow informed that some of the assets are available offline, from the bundle.
Basically, when UIWebView is loading a page, first thing that happens behind the scene is downloading the main *.html page. Then all the graphics/css'es/js'es etc are being downloaded.
You can let the html file be downloaded "as is", but intercept those requests that are going to download graphics (+ other assets) and provide them from local bundle. Please refer to this post:
http://robnapier.net/blog/offline-uiwebview-nsurlprotocol-588
and apply appropriate changes. The big win here is that from the webview's (and code that loads / maintain via JavaScript calls it's content) perspective - nothing has changed at all. Only the custom NSURLProtocol itself knows that some data was loaded from local storage.

Had the exact same problem. Subclassing NSURLCache to redirect the cache to cache images from local storage worked like a charm.
Here is the writeup that I followed:
http://www.cocoawithlove.com/2010/09/substituting-local-data-for-remote.html

TL;DR Complicated, avoid if you can, but possible.
If you still want to do it: don't do a UIWebView :loadRequest on the URL itself since it will trigger the start of downloading images very rapidly so modifying the images sources using Javascript will likely happen too late.
What you instead have would have to do is to download the contents of the URL on the native side and iterate the image tags there replacing the sources (quite complicated, don't use Regular Expressions to parse HTML btw, there are libraries for that), then injecting the modified HTML using UIWebView loadHTMLString:baseURL:.

Related

WKWebView intercept local file requests

I have a WKWebView in my iOS 11+ app where I need to load custom HTML from local in-memory HTML. I can accomplish this by using webView.loadHTMLString or webview.load(data), which is working fine.
This HTML references some required .js/.css/.png files. For normal web URL requests, WKWebView will just do this on the fly, loading missing files. But in this case, I need to intercept these requests, and provide the file contents, as some of it needs to be dynamically generated. So the .css files etc. I need to serve are not physically present as local files.
I thought this would be just a matter of implementing the decidePolicyFor methods of the WKNavigationDelegate protocol, but for some reason this is not triggered for local subrequests, so how can I accomplish this?
I also tried saving the HTML as a local temporary file and loading it using webView.load(URLRequest), but that does not trigger the delegate either. If it was a web URL, it triggers fine.
Let's say you render fullIosAppPath/page.html which has text like <img src="folder/1.png">.
In such case you need to have a file fullIosAppPath/folder/1.png in your app's folder. The WKWebView will load 1.png without any interception - it will just render the image.
So you can parse the HTML file before rendering it, and generate/load the requires resources like 1.png.
You can parse an HTML file with frameworks like Kanna, or write some simple parser by yourself.

Can webView load local storage files in iOS?

I want to make a hybrid app , because some files(like images) have been cached in my app's bundle already. If I use a webView to load a web page in server. and this webPage is use these images , can the webView to visit the app's bundle file system?
You could use some custom links to refer your bundle and change it on the fly from your app.
Let's say you use bundle://image.png then in your code you replace all "bundle://image.png" strings with someting like
[[NSBundle mainBundle] pathForResource:#"image" ofType:#"pnf" inDirectory:#"html_files"];
Anyway this approach creates a strong interdependence into the server and the app wich is not good I think.
I will use a more conventional approach caching images with something like: https://github.com/path/FastImageCache

Using NSURLCache to preload local assets for UIWebView

I'm working on an iOS application that displays locally-stored content (HTML files) in a UIWebView.
The problem is that some of the assets referenced from the HTMLs (for example fonts and images) take quite a while when loaded for the first time. I assume that the solution to the problem is to somehow cache these assets with NSURLCache before they're used in a UIWebView, but this seems to cause some trouble.
What I have tried so far:
Subclassing NSURLCache and overriding cachedResponseForRequest so that it returns a response with the asset preloaded in an NSData object. Preloading is done in the init method. The overridden cachedResponseForRequest seems to get called but for some reason the UIWebView still loads the asset from the file system.
Using storeCachedResponse:forRequest: to cache NSCachedURLResponse objects containing the assets before they're used in a UIWebView.
Neither of these seems to help. Any advice for where to look for the problem?

JQuery Mobile in iOS project without phonegap

Before I start, please don't yell at me telling me the answer is here or there, all my researches are polluted with phonegap results, and I don't use it, so I have troubles finding the answer !
I'm currently developing a native iOS app. It's almost done, except one section, which will contain a lot of text (basically all the rules of a sport, 10 sections with 2 to 18 sub-sections and a lot of text in each). I started the implementation, using a UITableViewController to display the main sections, and selecting a cell brings me to another UITableViewController with all the sub-sections of the selected section. Then, selecting a sub-section, you're supposed to get its content. What I've started to do is use another UITableVC with TextViews in the cells, using section headers to structure the text, but that's really not convenient nor is it nice to read.
So, I want to use html pages in UIWebViews. I'm thinking of using JQueryMobile, as I've used it in the past and I think you can get nice results pretty quickly. So, I have a couple of questions :
First, what do you think of the structure of this section ? (a UITableVC sending to another UITableVC, bringing up a UIWebView). How can I do something as readable as possible ? It's really the first time I have to put that much text in an app, so I'm not as sure of my design as when I develop more "standard" things. I want to do something better, but I have no idea how I can do something better..
Secondly, is JQuery Mobile a good option ? And this brings the real question : how do I include JQuery Mobile in my app ? I know I can include the .js and .css directly from JQuery's servers, but my app can run offline, so where should I put the needed files ? How do I include them in the html files ?
Thanks for your help, and again, if the second question has been asked/answered, I'm sorry, but when you search for JQuery Mobile and iOS, all you get is PhoneGap questions..
Just in case :
XCode 4.5.1
iOS 5+
Storyboard
ARC
Becuase UIWebView objects will cost a lot of memory, it's better to have only one UIWebView object in the native view. Don't add it for each row of UITableViewController.
You can write the web pages and include jQuery Mobile as normal and test them on Mobile Safari (by starting a server on your Mac and access it in your iOS device/emulator). After testing, add the directory in your XCode project as the blue 'folder reference'. Use the following code to load the page in UIWebView:
NSString *baseDirectory = [[NSBundle mainBundle].resourcePath stringByAppendingPathComponent:#"your_directory"];
NSURL *url = [NSURL URLWithString:#"your_index.html" relativeToURL:[NSURL fileURLWithPath:baseDirectory]]
NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:3600];
[webView loadRequest:request];

I cannot get the StageWebViewBridge to load external assets

I am using appfile:/. The path is correct; if I put it on screen and copy-paste it in the explorer it links to the image.
Is there anything else I need to do?
UPDATED I have updated the library, now is more easy to use. Can you test it?
I am the author of the StageWebViewBridge class. There is a known problem if you are using Android. Anyway, I have a working solution I will update the next week.
If the problem is not in Android, then send me some code.
I am also confused on how to access locally packaged assets. I put them in the HTML folder as requested and when I send a signal to the StageWebViewBridge to set the .src attribute of a video I'm not sure how to do it.
Without StageWebViewBridge and entirely in a website I can just reference the file for a video object via JavaScript directly e.g. swvRef.src = 'file.mp4';. This works perfectly fine. When I try to tell flash to send a call via StageWebViewBridge it does receive the call to the StageWebView (I have JavaScript reporting it). However when I try to set the .src of a video object I can't figure out the correct path.
The documentation says to put all things in a 'html' folder. I did so. No reference to a .src of 'html/a.mp4' or 'a.mp4' or 'htmlCache/a.mp4' ever makes the new javascript html5 video class work.
Bridge otherwise is working perfectly sending AS->JS and JS->AS. I'm just looking for info on how to reference packaged files. I want to play a video I put in the /html folder and so far, I just can't do it.
Got the same issue and fixed it with "appfile:/"
Why do you require "appfile:/ for a local html file ?
If the treated html/js/css is local and asset is relative (aka ../ or no http://) you should treat them as "appfile:/" ?
If the treated file is distant you do not have to handle assets ?
Is there a best practice to work with "appfile:/" ?
Actually I debug my html/js/css game in the browser but if I use appfile:/ it will no longer works. I will have to handle 2 behaviors.

Resources