I need a smart UIWebView (or a similar component) that can display/cache the full content of an HTML page on my server along with the images for offline access. And as soon as internet becomes available it will load the live version.
The app is a membership directory with member profiles. There's a main index and a page for each member.
Can you guys guide me to the right path on how to develop something like this? or point me to an existing library.
Thanks for your help I'm to new iOS development.
Two paths I can think of:
Wrap UIWebView, either in a subclass or a category, to encapsulate the loading logic
If network is online, load the URL directly and caching it using NSCache with the URL string as the key. NSURLConnection or something like EGOHTTPRequest will make loading easy.
If network is offline, check if the data exists in the cache. If so, use the -loadData: method to pull the content out of the cache and render it in the WebView. If it doesn't exist, display an error
Use a caching HTTP library, like ASIHTTPRequest to load the data. It can cache data it has loaded internally, and serve those cached results on subsequent requests if the network is offline.
ASIHTTPRequest looks a lot better on the surface, however there is a possible downside: It is a completely reimplemented URL loading system, based on very low level constructs (CFNetwork). So as Apple makes improvements to their high level libraries (NSURLConnection, NSCache) ASIHTTP doesn't get those advancements. Also, since so much of it's code is in Foundation, it will be a pretty major project to port it to ARC when that becomes generally available.
To load a local file on a UIWebView use fileURLWithPath
[WebView loadRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#"index" ofType:#"html"] isDirectory:NO]]];
It sure seems like you need to look at ASIWebPageRequest, which lets you cache whole pages offline:
http://allseeing-i.com/ASIHTTPRequest/ASIWebPageRequest
Related
I am quite new to Objective-C coding, learning at College at the moment so. Anyways, how do I perform a HTTP post with a UIWebview so that I can update the view when needed for a different flyer to put put there etc.
I may not even need to use HTTP post doing this, but my co-partner who is coding for Android insists I may need to!
Any help?
I'm not sure what you mean by flyer. But if you want a web page to appear in a UIWebView you don't need to use HTTP post, you just pass the url of a page to load to the UIWebView, or if you already have html content etc. you can load that content directly.
You can make HTTP requests directly but you probably don't need to. What exactly is it you want to display in the UIWebView?
To make an HTTP Connection start by learning about NSURLConnection at iOS Developer Library
The first thing you're going to want to start with is making your NSURL objects then make your NSURLRequest with the parameters as well as the URL of your request. Then make a NSURLConnection and initiate the connection either asynchronously (preferred) or synchronously. If you want a synchronous (blocking) connection initialize it like so
NSError *error;
NSURLResponse *responseHandler;
NSData *response = [myNSURLConnection sendSynchronousRequest:myNSURLRequest, returningResponse:&responseHandler,error:&error];
I am trying to utilize the NSURLCache when loading a link in UIWebView. Inside the UIWebView I have a bunch of links of images and I want to cache this so I can utilize this later. How do I do this? I have set the NSURLSharedCache size.
EDIT:
I am doing a loadHTMLString:htmlString baseURL:baseURL to load the content into the UIWebView, maybe that's why it's not calling in, right?
If you are expecting disk cache, rather than memory cache, then you should take a look at SDURLCache:
https://github.com/steipete/SDURLCache
From the README:
On iPhone OS, Apple did remove on-disk cache support for unknown
reason. Some will say it's to save flash-drive life, others will arg
it's to save disk capacity. As it is explained in the
NSURLCacheStoragePolicy, the NSURLCacheStorageAllowed constant is
always treated as NSURLCacheStorageAllowedInMemoryOnly and there is no
way to force it back, the code is certainly gone on this platform. For
whatever reason Apple removed this feature, you may be interested by
having on-disk HTTP request caching in your application. SDURLCache
gives back this feature to this iPhone OS for you.
I need to work with ASIHTTPRequest in my app but i'm an absolute beginner in everything that concerns http, json, connections to server and stuff like that, so i decided to learn the basics first and i've got few really dumb questions for you. I have already googled looking for the answers, but all in vain
1)Does NSURLconnection have something to do with http protocol and http prequests? Is it useful for me to get acquainted with this class since i'm gonna work with http requests?
2)A huge problem of mine is that i do not have a web server yet to test my requests and i've been wondering if there is a free web server available for those who just want to upload/download data (images and may be something else) to/from it in order to learn basics of working with servers.
3)As far as i know development of ASIHTTPRequest library has been ceased. Does it mean that this library will become unavailable soon? Should i look for a different library? And btw is there a better one?
Thanks in advance
1.you use NSURLConnection to create a request object from a NSUrl. Here is an example, I used it to load a url to a UIWebView :
//Set the URL to go to for your UIWebView
NSString *urlAddress = #"http://google.com/";
//Create a URL object.
NSURL *url = [NSURL URLWithString:urlAddress];
//URL Requst Object
NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];
//load the URL into the web view.
[aWebView loadRequest:requestObj];
You can read more about it here:http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSURLConnection_Class/Reference/Reference.html
NOTE : also look at NSMutableURLRequest, which is a subclass of NSURLRequest
2.To test, you can install apache on your computer and access it using http://localhost/.
If you are using windows, download WAMP : http://www.wampserver.com/en/
and if on mac, just search google how to install apache through terminal.
3.I havent used ASIHTTPRequest in a long time but as far as I remember it was a good library . if it is being ceased, then that probably means they wont be publishing anymore updates and/or fix bugs, so yes I think its better to use an active project that is being updated constantly. I also havent found any warning on their site about it, so I doubt they are stopping the project.
1) Yes NSURLConnection deals with HTTP and others protocol. But it isn't so simple to use than ASIHTTPRequest
2) Create a dropbox account and use the Public folder. Then right click on the file and select Dropbox > copy public link. You have a Webserver!
3) AFNetworking is really great
Some Background
I have an iPhone app with three UIWebViews, each used to show a different type of page. (The content is specifically designed for this purpose, they're not real web pages.) There are links associated with each specific web view. For example, a link tapped in WV1 might need to load in WV2 because it's a WV2-style link. (The webviews are in a paged UIScrollView, which I use to scroll to the currently loading webview. I can tell which URL loads where based on it's path.)
It makes sense to me to have a single UIWebView delegate that responds to all URLRequests (via webView:shouldStartLoadWithRequest:navigationType) and somehow decides which should load where.
The HTML I want to load in the webview isn't fetched directly from a page. I do something like [NSDictionary dictionaryWithContentsOfURL:] to get the object, part of which is the actual HTML. (Additionally, this might come from the network or a local cache.)
The Question
I need to cancel a request in one UIWebView and then load some arbitrary data into another. How should I be doing the subsequent load, so that it bypasses my interception?
Should I stop all intercept all NSURLRequests via the webview delegate method, then send a new NSURLRequest, that will actually get loaded, to the correct webview? I was thinking I'd subclass NSURLRequest so I'd be able to tell original requests separate from my doctored requests. But again, I don't want to make straight NSURLRequests, I want to fetch an NSDictionary and use one of it's values as the HTML.
I saw this article on filtering what loads in a UIWebView, but I don't think that's exactly what I want.
I'm trying to work my way through the URL Loading System Overview, but there's a lot there.
Ended up using custom URL schemes to identify the requests that I wanted to load vs. the ones I wanted handled.
I am just testing an app to get data off our web server, previously I had been using:
NSURL, NSURLRequest, NSURLConnection etc. to get the data that I wanted.
But I have just noticed that if I swap to using XML I can simply do the following and pass the results to NSXMLParser:
NSURL *url = [NSURL URLWithString:#"https://www.fuzzygoat.com/turbine?nbytes=1&fmt=xml"];
Am I right in thinking that if your just after XML this is an acceptable method? It just seems strongly short compared to what I was doing before?
gary
That code only creates a URL object that represents a URL. It doesn't make any request or download any data. You still need to use NSURLRequest and NSURLConnection in order to actually download any data from the server.
Also, stay away from methods like 'initWithContentsOfURL:` and friends, unless you understand that they will block the thread that they are called on until complete. For network services, this method shouldn't be used because it'll block your UI for an indeterminate time, because you can't predict how fast the internet connection will be wherever the app is used.
NSURLConnection's asynchronous request system is exactly what you need. It won't block the UI, and provides a nice encapsulated interface to downloading data from a remote location.
This is definitely the right way to go. There do exist many different connection methods (including my favorite, ASIHTTPRequest) and many, many different xml parsers (including my favorite, KissXML) that are faster or more memory efficient than the Apple built in methods.
But to answer your question, yes, your logic and design pattern is correct.
UPDATE: Because Jasarien seems to think the question talks about asynchronous actions, I will discuss that here. ASIHTTPRequest handles async very very easily. Just check out the quick samples.
Depending on how much XML you get back from the web service, NSXMLParser may not be ideal because the entire XML document has to be read into memory.
Memory is pretty scarce on an iPhone, so using a SAX parser like that in libxml2 is probably better for larger XML files. Instead of reading the entire document into memory, the XML is streamed through and parsed for specific nodes of interest. The memory overhead is lower because less data is stored at once.
Once a node of interest is parsed, an event handler is called to do something useful, like store the node data somewhere.
In this case, take a look at Apple's XMLPerformance sample project for example code.