Move a folder to Documents directory - iphone

The iPhone application I'm working on comes bundled with 20MB of images in the application directory and I need to write new images to the documents directory over time.
Ideally I'd like to move the initial folder to the documents directory, copying the folder would mean wasting 20mb of the users disk space.
Failing that I'll create the required structure in the documents directory and leave the initial images in place, but that would mean checking in two places every time I want to display an image.
Is there a way of automagically searching the application bundle and documents directory when building an image path?

To answer your first concern: you can’t move anything out of the application bundle. Any modification of said bundle invalidates the signature and will render your app non-functional on all but jailbroken iOS devices.
Now, onto the challenge of copying images out: To find something in the main bundle, you’d do this:
NSString *imagePath = [[NSBundle mainBundle] pathForResource:#"myImage"
ofType:#"png"];
For an image, though, you’re better off doing this:
UIImage *imageFromBundle = [UIImage imageNamed:#"MyImage.png"];
That will do caching for you in a way that loading the image directly won’t.
I don’t know why you’d want to copy the image out, but it seems that maybe you have an initial set of images that may or may not be replaced. I’d recommend, then, instead of copying out of the bundle, look for the image first in the Documents folder, and if it isn’t there, copy it out of the bundle. That allows you to replace the images without copying from the bundle or modifying the bundle.

AFAIK the bundle is read only. So while your "move" idea is a good one, I am fairly certain Apple does not allow for it currently.
Is there a way of automagically
searching the application bundle and
documents directory when building an
image path?
I can say that I have done this for images but you have to create the magic yourself. I wrote a class that I would call with the name of the image as a parameter. That class would first look in the documents directory, then look in the bundle and finally look to a website for the image. When it found the image it returned the UIImage. A bit of a pain to initially setup, but once in place it is quite useful and I am glad I did it.

Related

How to store data with images in local for later use iphone

I am able getting data from server and display on UITableView, It's working fine. But when I go to another tab and return to same tab it will call to server for data. I want to store data locally once get from server.
Please suggest me your thoughts.
Thanks!
You have to store the file on the device and this is possible in a few ways:
Store the files in the App its Documents directory
Store the files in the App its Library/Caches folder
Store the files in the App its Library/ folder
There are a few considerations for each option:
Files stored in the Documents folder are by default backed up by iCloud. You really have to think if this is necessary because you're eating up iCloud storage space from the user (for which he/she may pay).
Storing files in the Caches folder is a good way, but they may be deleted by iOS if the users disk is running low on space (therefore the name Cache).
Storing files in another (manually created) folder on the device will keep them as long as the app is installed. No iCloud backup or no removal by iOS
Getting the location of the specific folder can be done using:
[[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
Where you have to replace NSDocumentDirectory by NSLibraryDirectory when you want the NSURL to the Library folder.
Storing data is as easy as creating an NSURL which points to the location where you want to store the data and then call the writeToURL:atomically: method on the NSData you want to store.
Converting UIImages to NSData can be done using UIImageJPEGRepresentation or UIImagePNGRepresentation.
i would prefer to use the HJCache library for the temporally store images.
For that followings are the reasons to implement the HJCache open source library.
Make it easy to use asynchronously loaded images in iOS apps.
Make it easy to use a shared file cache.
Make memory management ‘just work’ according to Cocoa norms.
Support typical cases of viewing images, eg scrolling through a list of tweets showing the tweeters profile pic, swiping through a photo album loaded over the net.
Allow the library to be used for other kinds of data too.
For more detail and tutorial visit the github and author blog

iphone update some files in application

I'm creating one iphone application that uses and xml to get some data from and a few images. Lets say that originally these files will be in the application bundle. But then I want to make my application to get updates from a web service. So lets say I download a new xml and new Images.
Where do I save them? I think I will be able to save them in the application "cache" right?
But then How do I make my application check if this resource exists in the cache, then load that one...else load the one in the application bundle?
iOS to be used 4.3 but if it makes it easier we can go to 5.
You will have to use NSFileManager to save the file to and load it from the document directory. Check out the following link, which actually contains all the info you need:
http://www.friendlydeveloper.com/2010/02/using-nsfilemanager-to-save-an-image-to-or-loadremove-an-image-from-documents-directory-coding/
If [UIImage imageWithContentsOfFile:fullPath]; (fullPath being the NSString with contains the path to your image in your document directory) returns nil, then the image is not present, so you'll have to load the default image from your bundle.
You can access your default bundle files using [[NSBundle mainbundle] pathForResource:#"yourFileNameHere" ofType:#"yourTypeHere"] This will return the path to your file in your bundle and you can just pass it to [UIImage imageWithContentsOfFile:]
This example only applies to UIImage, but you can easily adapt it to use other classes. I think the UIImage example is enough for illustrative purposes though.
You'll probably want to create a versioning scheme. After the app starts (or periodically) call the web service for a very cheap call to ask what version it has. You'll know what version you have (write in a plist or have the version number in the folder structure). Another options is pushing a notification.
The next thing you'll have to think about is how the app reacts to getting a new data set. You could do it only on start up but that might block the start up experience if you're bounding it to a web call. The other option is to allow the dataset to change while the app is open. You could have a model that uses NSNotificationCenter to notify your views and controllers that the data has changed. I would probably version the storage as well (folder per) to help with the transition.
As for how, you can make web requests with something like ASIHttpRequest, NSFileManager to write to the documents directory, and plists to save settings like version.

How can I save pdf's to my app resources folder, and access them in run-time?

I have an app I'm designing that will allow for lots of PDF viewing. There are a lot of different languages available, and so if I were to include all of them in the app, it would be like 100+ mb in size which just won't fly.
So I'm thinking that I am going to put the pdf's on my server, and access them with a direct download link like this:
http://mysite.com/pdfs/thepdf.pdf
Which will return the exact pdf I want. So I'm wondering how I can go about accessing these resources as I download them on the fly?
I imagine I need to save the pdf's to the app resources folder? And then when a tableView row for the pdf is selected, I check if the pdf is in the resources folder (how do I do that?), and if not, pull it down off the server, and load it into my view?
I think I have an okay idea of what I need to do, just not very clear on the code to do it. Can anybody post the code for accessing the resources folder (if that's actually what I need to be doing), and maybe the code for how to check if something is in the resources folder?
Thanks!
Have you considered using a UIWebView to view the PDF instead of downloading and loading it yourself? UIWebView should take care of caching, so you won't have to worry about that.
Assuming that a UIWebView won't work, to download PDFs and see if they exist, you need to store it in the Documents folder. The resources folder cannot be altered after you submit your app to Apple, but the Documents folder in your app is completely fine. To access it, I would actually recommend ConciseKit, which can be found on GitHub. It gives you a helper method to access your app's document directory. The helper method is
[$ documentPath];
Then you can get the path for a file by doing
[[$ documentPath] stringByAppendingPathComponent:#"file.pdf"];
So that is how you get a path to a file, to check if it exists, you want to use NSFileManager.
[[NSFileManager defaultManager] fileExistsAtPath:#"path from above"];

iphone embedding images in the executable file

When releasing to the application store someone wrote in an offhand comment that you need to avoid embedding your images into the executable.
How do you do that?
I've seen code in various books that suggests encoding images as C byte array constants in the source code, and I can say that that's definitely a bad idea for reasons ranging from inefficient pixel formats to unsalvageable memory. That would qualify as "in the executable file" in a way that bundle resources don't, since bundle resources are packaged alongside the executable rather than within it.
I am not sure if I get you correctly, but maybe he meant accidentally adding image files to the Compile Sources category in your build target? This usually does not happen with images, but i have seen it happening with js files.
Perhaps they meant that you should only include images in the bundle that are essential.
The bundle is essentially read-only so you cannot remove an image from the device that is in the bundle. Therefore placing lots of example images that you expect a user to remove/not want is not a good idea because when the user deletes the images from inside your app no space on the device will be reclaimed.
Of course it is fine to place images in the bundle just make sure that they are required and are not taking up unnecessary space that the user cannot reclaim.

(iphone) How to store images in directory structure (vs flat documents directory) and related questions

I'm looking for a good way to manage many image files in my app.
When the number of images to maintain gets large, it seems vital to have a directory structure to hold them.(to organize images and to support duplicate image names)
Since normal way of storing images in documents directory(by adding images to xcode's resource folder) doesn't seem to support directory structure,
I probably need to use something called bundle.
Here are questions.
It's not clear to me what's the difference between "documents
directory" and "bundle". Are they
just names to specify directory path
inside an iphone application? Since
documents directory doesn't support
directory structure, I guess it's not
a regular file path in iOS? (I'm
looking for a definition or overview
description on those two terms enough
to help answering the following
questions)
How do I create a tree structure directory to store resources?
How do I add files to the created directory?
What is the step (probably in xcode) to add new files to the
directory as project grows? note:
question 3 deals with initial set up,
4 deals with update.
What happens to files under documents directory and bundle when
user updates the app? Since many
applications store user data
somewhere, there must be a way of
updating an app without wiping out the
saved user data. ie. How does
"documents directory" and "bundle"
behave in update situation?
So called "resource bundle" refers to the "bundle" used in above
questions?
Thank you.
Your app is a "bundle". It's represented by an NSBundle object. On iOS, this is the only bundle you are allowed to use; you can't create another bundle and import it into your app.
However, you can add a subdirectory to your app's bundle. In Xcode 4, select your project in the navigator and click on the Build Phases tab. Add a new build phase (bottom right), Copy Files. Move it up just below Copy Bundle Resources, and rename it something meaningful ("copy interface images", or something). You'll notice you've got a Subpath field there - that's your directory in your bundle. Drag the files you want in that subdirectory on to this build phase, and then you can access them through the normal methods in NSBundle, UIImage, NSData and so on.
Wish it was easier? Me too.