In our iOS app we have close to a hundred image files in resources bundle. Now we want to make them network based since the images may change (updated/no longer needed/additions) at any time. We are debating at what approach would be optimal. From what I have read, I understand that the resource bundle will not be editable on the device. So, when I start the app, I will check from the server if there are any image updates. If so, I will download the changed images and then save them to documents directory. Then in the app, for every image, I will basically have to check if it is in the resources bundle, then grab it from there. Else pick it from documents directory and display it.
Another approach is I don't have anything in the resources folder, I download all images on app launch from the server and store them to documents directory and then on, download the changed files at subsequent app launch. Here I am eliminating the check on resources folder if an image is present or not and my app bundle size would be reduced.
The third approach would be to copy the files from my resources directory to the documents directory on first launch and thereafter continue from documents directory.
Any suggestions on what would be a better approach or all of them would be similar from the performance point of view?
IMO, option three offers the best balance between eliminating needless code and preloading as much data as possible. You don't want to make the user wait for 100 image downloads when the app starts the first time, so pre-load as many as possible. The copy code is simple and will only be used once. So that eliminates the runtime checks you'd have to do with the other options.
No worries, performance will not be an issue, unless you use a particularly unwise image lookup algorithm.
Filesystem traversal should be pretty fast for such a small amount of files.
Before implementing something yourself, I would recommend looking at something off the shelf for Image Caching. Namely EGOImageView from EnormEgo.
I have used it in several applications which are dependent on grabbing images from URLs. It handles everything for you, you just set up a 'background' image for it to show while it goes about it's business of grabbing the URL based image in the background. The second time you use it, it's available immediately. Definitely gets my vote for ease of use...
p.s. it's free to use
Related
I am developing an online multiplayer game using GWT and I want to reduce traffic by downloading images and sound files before they are utilized. I am using the method Image.prefetch for the image files. Is this the right way?
Concerning the sound files, I do not know exactly how to ensure that they are downloaded before the game starts. I am using the library gwt-voices and currently invoking the method play() on all needed sound files with a sound controller with default volume 0.
In both cases, it seems like the files are fetched once and then cached. This is fine but I think it might be better to have them downloaded them by the client and access them locally - if this is possible.
I'm not sure if it will work with sound files but you may wish to use a ClientBundle. At compile time this will create a single large image so when you first ask for one of the images the client will retrieve the entire large image and then you ask for and get the individual images. This cuts down on the multiple requests needed to otherwise retrieve each image individually.
https://developers.google.com/web-toolkit/doc/latest/DevGuideClientBundle
Also, you should look into code splitting which would probably be useful as well.
https://developers.google.com/web-toolkit/doc/latest/DevGuideCodeSplitting
Some discussions in Stackoverflow say that storing the picture in DB is a bad idea (a because overtime, the number of images get large & may lead to app crash). So, either
a. the image can be stored in the iPhone itself & only its location can be stored in the DB
Potential Issue: The image might get removed (outside of the app) & the app might not be able to load them the next time
b. the image can be shrunk to a small size (say, 100*100 pixels) and stored in the DB
Potential Issue: will size be an issue if the image is shrunk to just 100x100pixels?
c. Doing both (a) & (b). So, small versions of the images will be stored in the DB and then, retrieved & displayed in the App, whereas, if the user chooses to see the original version of the image (whose probability is low), then that'll be fetched from the local directory & shown.
Your suggestions please? In my opinion, (c) seems a good option to go in for, in case (a) has the potential issue mentioned.
It really depends on where the images are coming from. Are they being downloaded from the Internet (or imported from the user's library / camera) after the user installs the app, or are they bundled with the app from the App Store?
If the images are being downloaded / imported, the best solution is to store images in the filesystem following the recommendations in http://developer.apple.com/library/ios/#qa/qa1719/_index.html
Basically, if the images cannot be replaced or recreated, store them in the <Application_Home>/Documents directory and do not set the Do Not Backup attribute. These items will be backed up to iCloud, and this data does persist for at least some amount of time even if the app is deleted from the device. (Remember that your users do not have unlimited iCloud space. Be responsible.)
-However-
If the images are bundled with the app, the best solution is to import them directly into your Xcode project and reference them from there. This way you know they are always available even if the user deletes and reinstalls the app.
I would definitely stay away from storing image data in the databased whenever possible. There are simply better, more efficient ways in most any scenario.
HI,
For how long data can be saved in Cache folder. I want to cache lot of images which I will be using multiple times. What should be the best place to save them?
Also, these images will rarely change like once in a week kind of. So how and when should I trigger the image refreshing without hampering the app experience.
I assume you’re referring to ~/Libraries/Caches/. The system doesn’t automatically remove stuff there, so the answer is “indefinitely”. If you’ll be adding unbounded amounts of data, you need to clean it out yourself.
Keep in mind that by putting data there you’re effectively promising that your app won’t break if it’s deleted at any time, and it won’t be backed up.
Just refresh the images in the cache when you download new ones. Downloading new ones depends on the images, and where they are used. Eg you could cache the Cocoa-Cola Logo indefinitely as it never changes, but say the Google logo (including the doodles) should be checked for pretty much every day, as it can change (like it has changed today)
I need help with downloading from webserver...
What i currently do is get XML file from web servers that contains image locations, parse XML, download each image, store image on iphone, and store image name to sql database.
This takes lots of time because there is large amount of images to be downloaded and i am downloading one by one.
My app update just got rejected because reviewer decieded that downloading is too long... What is funny, last two updates passed without problems..
I was thinking about zipping those images on server and sending zip file to iphone, unzipping it there, or packing images together with binary and sending it to apple.
Any advice on how to make download faster, would be appreciated. Thanks.
BTW, zip won't help with images. They are already compressed, so it will just add overhead. Make sure your images are not any larger than you need for display and I'd do what Mario suggested above and download them in multiple async calls (at least make the one big call asynchronous.)
A key principle of UI design is to display partial results (unless they are invalid or misleading) so that the user understands that progress is being made.
If you really need all the images to make it valid, you can download a few and display them grayed out (alpha = 0.4) or something so that it's clear that this is a partial result, but that progress is being made. The reviewer probably felt that it was taking too long to startup.
Do you change those images often? Or only once per release if at all? If they change with each release only I'd package them. If they're almost never changed, go with the one huge download (so people don't have to redownload when updating) and if they're change often, download them file by file but try to do 2-3 files at once using asynchronous download (if supported).
1) I would use something like an NSOperationQueue to download around three images at a time in the background. Much more than that and the UI starts getting choppy.
2) Also display some kind of loading indicator while this is going on.
3) What format are your images in? If you are transferring over the network you should use JPG, and consider setting the quality level to something smaller (say 6 even 5). To offset the loss of quality you could send down larger images, even with the larger number of pixels you can easily be better off with a lower quality compression.
4) If you have to use PNG to preserve transparency, consider using PNGCrush on the images before sending. As noted, zip will do pretty much nothing.
One way to speed up download of those images is to put them on a CDN. Some CDNs, like Limelight have special network optimizations for sending data to mobile devices. They also just do a better job of routing content, and have higher capacity for transmitting content. What's nice about this approach is that you might not have to change your app. However CDNs can be pricy.
Likely, your images are just way too large. You said you're worried about the 20MB app limit, but I think at that point, your images are just way too large for the phone.
Rather than zipping the files, I'm pretty sure you need to downsample the size of the images. Not only that, but you should only download the ones that you need, when you need them.
If you still want to have bulk downloads, why not have it as a side option rather than the default implementation?
My problem is that my application size is very high,
is there any idea to reduce size of application?
if i make application without content and content is uploaded my server then how i sync the application with content put on my server?
i want to know that once user download application after that when he use application then we stream the content and save his document folder.
once user stream then never required for streaming.
is it possible????
Thanks,
Reducing the size of your application depends on the TYPE of contents of your application. I highly doubt that the application code is the cause, and since you did not mention what they are I am assuming they are some kind of resource.
If your resources are images, try to use image compression programs. Or convert them to smaller sized images or optimize the images.
If your resources are documents / text files / files that have a high compression ratio when zipped. Then you can try to zip your resources and access them inside the compressed file (this will mean additional coding, and probably slower in performance).
These are just examples.
It is not advisable to stream large contents because it uses the network bandwidth which, depending on the user's plan, can cause a big spike in phone bills.
Yes it is possible that you can download your content and can save to application's document folder, when user runs your application for the first time. Thought it may affect the first impression to your user as it will take time to download.