iOS Cache a UIWebView - ios

I've written an iOS app that loads up an HTML5 web application inside a UIWebView. I'm trying to make the app cache everything in the UIWebView for use while on a 3G connection rather than load it all again.
It needs to follow all links while on a WiFi connection and download all pages and images. When on a 3G connection it should then load everything from the cache.
Is this possible? Any ideas on where I should start? Do I need to make my HTML5 application load all pages in the background rather than have the app do it?
Thanks for any help!

Firstly I would use Reachability to detect if there is a WIFI connection and your server is accessible. This way you can handle both 3G connectivity and no internet connection in the same way. (accessing the cached pages). It also means you can use the cache if you have WIFI but still cannot reach your server.
Reachability sample code
I would either download a zip file of your web pages and all the associated assets (if it is a fairly static website) and unzip and store them in the local file system. You can then point your UIWebView to the local directory when there is not WIFI.
You could use something like Zip Archive to handle this
ZipArchive GitHub page
If this is not an option then you could get the HTML from the page when you load it in the UIWebView. The problem with doing this is you are reliant on the user accessing pages in order to cache them.
You can use this to get the HTML code and store it locally:
// Determile cache file path
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *filePath = [NSString stringWithFormat:#"%#/%#", [paths objectAtIndex:0],#"index.html"];
// Download and write to file
NSURL *url = [NSURL URLWithString:#"http://www.google.co.uk"];
NSData *urlData = [NSData dataWithContentsOfURL:url];
[urlData writeToFile:filePath atomically:YES];
// Load file in UIWebView
[web loadRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath:filePath]]];
You could use this code to get all the web pages in the background as well. To do this you will either need to hard code all the required URLs and look them up individually or better still download a list of web pages from your site first.
You could create a web service (JSON is probably your best option for this) giving a list of URLs to download. You could then parse through this JSON and use the URLs to feed into the code above and cache the HTML locally.
Just remember to be careful with your hyperlinks and links to any images and CSS within your HTML as this will break your cached website if they are looking for your full online URL rather than a relative path.

Related

Replace Data Container of an iOS .ipa File

I have an app that downloads a whole bunch of data from over 100+ APIs upon successful login. I successfully download the data, and then use iExplorer to extract the data container folders (Documents, Library and Tmp) from the fully loaded application.
I would like to take a blank version of the original app, in .ipa format, and insert those data container folders into that fully loaded .ipa file. Then I will be able to take this new fully loaded .ipa, and use a deployment software to deploy it to a bunch of local user's devices. So everyone will have this fully loaded app.
Please, has anyone done this? Please provide some feedback, and don't argue with my methodology, because this has be done this way due to requirements. Maybe there is a step I'm missing? I'm not sure.
With the source code in hand, you can run the app in the simulator (no need for iExplorer), wait for it to download all the files and browse to the folder on your computer where the app was installed.
From there you can put aside any files you want along with their respective folders. If you're using Coredata there should be a SQLITE database file there somewhere (typically in your Application Support folder) and this might be all you need but it is hard to tell without looking at your implementation details.
Once you have the files you need set aside, add them to the app bundle via Xcode and create code to check whether files already exist (in which case you don't want to replace them), and if not copy all files needed from the bundle into their respective folders.
Here's some semi pseudo-code for you:
NSDictionary *userPrefs = [[NSUserDefaults standardUserDefaults] objectForKey:self.email];
if (![userPrefs[kInitialSetupCompleted] boolValue])
NSFileManager *fileManager = [NSFileManager defaultManager];
NSURL *destinationFilePath = ...
NSURL *seedFilePath = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:kCoreDataStoreName ofType:nil]];
NSError* err = nil;
if (![fileManager copyItemAtURL:seedPath toURL:destinationFilePath error:&err]) {
NSLog(#"Could not copy seed data. error: %#", err);
// Deal with error
} else {
// Set user defaults kInitialSetupCompleted to YES
}
}

IOS creates new Application ID everytime I open the app, or run it from Xcode

With the upgrade to IOS8 and Xcode 6.0.1, I have noticed that adding images, writing them to file, and displaying them is broken in my app that has been working for over 2 years. It works fine at the time of taking the photo and saving it - it displays it fine. I store the FilePath in Core Data. But as soon as I close the app and reopen, or run the simulator again, it disappears.
I have tracked the problem that every time it runs on both the device or the simulator, the documents directory string changes, with the APPLICATION ID changing, so the image is not found in the path as it can't seem to access the path of the previous APPLICATION ID that it had.
I looked for this and couldn't find any answers. Has anyone else seen this and have any suggestions for how I can get around it. Thanks so much!
Kat
Edit - I have added this code example. Every time I run my app, this is the path that changes.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSLog(#"documents directory %#", documentsDirectory);
Store your relative path, here by calling the temp directory, but not the full absolute path. The App container is changed at every start, due to sandboxing safety.
NSURL *tmpDirURL = [NSURL fileURLWithPath:NSTemporaryDirectory() isDirectory:YES];
NSURL *fileURL = [[tmpDirURL URLByAppendingPathComponent:#"MyPic"] URLByAppendingPathExtension:#"jpg"];
NSLog(#"fileURL: %#", [fileURL path]);
In the end I added the files into Core data, as they were referenced from Core Data objects.
This is a new change in iOS8 for safety enhancement, so you never should keep absolute path.
You save a file name instead of file URL. Each time when you use file URL, you make file URL from file name by your computed property.

getting csv to download in iOS

I'm aware that there are similar questions posted, but this is a very specific issue that may or may not be related to code, it might be due to where I'm sourcing the file, and I need some advice.
I have an iPad app and am detecting whether there is an internet connection. If there is, then a .csv file is downloaded, saved, then split into an array. If not then a file held in the main bundle is used.
When using the file held in the main bundle, I can extract the data. The problem I have is when I try to download the .csv. The file is held on Document Manager, a Content Management System that is the only secure area for the file to be held for the company I work for and is therefore unavoidable. If I use this code:
NSString *urlString = #".../view-document.cgi?f=fundsspreadsheetc.csv";
(sorry, I need to keep the full link confidential)
NSURL *csvURL = [NSURL URLWithString:[urlString stringByAddingPercentageEscapesUsingEncoding:NSASCIIStringEncoding]];
NSData *urlData = [NSData dataWithContentsOfURL:csvURL options:NSDataReadingMappedAlways error:nil];
then urlData returns nil.
The original url opens the file on a windows laptop, but with a file name of view-document.cgi. I don't know if this is relevant.
If I change the url to:
"
http://download.finance.yahoo.com/d/quotes.csv?s=^GSPC+^IXIC+^dji+^GSPC+^BVSP+^GSPTSE+^FTSE+^GDAXI+^FCHI+^STOXX50E+^AEX+^IBEX+^SSMI+^N225+^AXJO+^HSI+^NSEI&f=sl1d1t1c1ohgv&e=.csv"
from a question set by shebi, then my code works.
What do I need to do to get my file to download?
much appreciated
Thanks for the help, it was problem with the link.

Offline html5 in a UIWebView

I will have to create an offline app from a received html5 file (sort of just display it in a UIWebView, I have no idea wether it will be multiple pages or just one). I have a very limited knowledge about html programming and such, and unfortunately due to a limited time frame I can't spend much time reading up about it. Are there any limitations to trying to display this offline in a webview or maybe other 'catches' that I need to be aware of?
Thank you in advance.
If you are not changing the contents of the webpage, you can embed the HTML and all files and you won't have to worry about HTML5 since it's all already included
So create the HTML file and keep it in a folder (let's call it "index.html" and the folder "code" for this example) and drag it into your Supporting Files folder in xcode. Click the "Copy items..." checkbox and "create folder references..."
Then use this code in your ViewDidLoad:
NSString* filePath = [[NSBundle mainBundle] pathForResource:#"index"
ofType:#"html"
inDirectory:#"code"];
NSURL* fileURL = [NSURL fileURLWithPath:filePath];
NSURLRequest* request = [NSURLRequest requestWithURL:fileURL];
[webView loadRequest:request];
IF YOU WANT TO PULL A FILE OFF THE WEB:
to begin the HTML5 file, start it with
<!DOCTYPE HTML>
(seriously, that's all that's needed for "html5")
Then to make it so you can view the files offline, create a "manifest" file, so next add the line
<html manifest="example.manifest">
Then in a text editor list all the items to be included for offline (index.html, logo.jpg, page2.html, logo2.jpg, etc)
boom, done
These 2 links are good resources for offline content
[http://ofps.oreilly.com/titles/9781449383268/chapOfflineApplicationCache.html][1]
http://www.html5rocks.com/en/tutorials/appcache/beginner/
[1]: http://ofps.oreilly.com/titles/9781449383268/chapOfflineApplicationCache.html [removed from web]

iOS - PDF Loaded in UIWebView then save to iBooks using UIDocumentInteractionController

I am loading a PDF from the web using a UIWebView, which works great and lets me interact with the PDF how I want.
Next I would like to be able to save that PDF to iBooks, so I am using a UIDocumentInteractionController. In reading the docs it seems that you can only use UIDocumentInteractionController with local files rather than a remote file like I have.
My question is, that PDF that UIWebView loads must be cached somewhere, so I really have to do another call to download that same file, just to have UIDocumentInteractionController be able to load it as a local file? Or can I somehow use that same file that UIWebView has already loaded?
You can't directly access the data that the UIWebView caches. If you only want to download the PDF once (which is the right way to do it), save the file locally yourself. Then load it in your UIWebView like so:
NSURL* url = [NSURL URLWithString:#"path to local file"];
NSURLRequest* urlRequest = [[NSURLRequest alloc] initWithURL:url];
[myWebView loadRequest:urlRequest];
[urlRequest release];

Resources