Handling cache right? - ios

I’m developing an application.
I have came to the point where I can’t decide what’s a good caching strategy:
The app shows restaurants nearby with images and videos:
If you go to a restaurant it pops up. If you go away, it disappears. If you go there again, it appears again.
Therefore I cache the photos with SDWebImage and the videos with a custom made video cacher.
So in a normal case when the user is walking in the city, the app downloads lots of images and videos, which may or may not be seen again.
I don’t know how other applications are working, but I made a function that deletes all image-video cache (that are not visible anymore) every 5 minutes.
Is that a good straregy? Or would it be better not to delete manually old photos-videos cache, IOS does it by itself?

Related

How do I test PHImageResultIsInCloudKey?

My app has a custom photo picker that uses the Photos framework to browse albums and select a photo. I have isolated reports of a very specific bug that occurs only if the user (a) has iCloud Photo Library turned on, (b) has Optimize Storage turned on in their Photos settings and (c) that specific album and/or image has been moved off the device.
In this scenario, it looks like no actual image is returned to the closure I pass to PHCachingImageManager#requestImage. Instead, from what I gather, PHImageResultIsInCloudKey is included in the info dictionary and I need to re-invoke the request with isNetworkAccessAllowed set to true.
However, in my own testing, I just can't get this specific scenario to occur so I can confirm that my fix works. Even with iCloud Photo Library on and Optimize Storage on, I still always get an image back and never get PHImageResultIsInCloudKey.
Is there a way to force a situation where the image is off-device and has to be loaded from the cloud?
I was working with PHAssets and had a similar problem, where a user device had an unimaginably vast photo library (meaning lots of photos were off-device), which was causing performance issues.
To replicate those conditions, I made https://github.com/jrturton/DiskFiller, which, as you might guess, writes massive files to your device until it is full, which has the side effect of triggering the "optimised storage" for iCloud photos to kick in, moving older photos to the cloud. Maybe that can help.
Probably best to run it on a test device if you have one :)

iOS app file storage. YouTube, parse.com or local?

I have an iOS app that uses a lot of pictures and videos. Currently, I use parse.com as backend and I store the pictures in parse.com database. Imagine I have 200 tasks, each task with two pictures and one video. Now, each user will have his own set of tasks, for example, user A may have 20 tasks, user B 40 and user C 50, all different tasks included on those 200.
Now, I'm worried about app performance, not so much server storage and other structure details...
I don't think including all pictures in the app bundle is a good idea, because user will use only about 40% of the pictures at a time, so it wouldn't be wise to include it all in the app. Instead, I have the pictures in database and when user needs, the app makes a request and gets it. Am I right about this? Is this the best performance?
Regarding the videos, should I store the videos in youTube.com or in my parse.com database? I think youTube is the best option because I can live stream the video whether in parse.com I will need to download the video first. Does that make sense?
If there are any other services or better way to handle pictures and videos in an iOS app, please let me know.
Regarding images - the best performance here is to store them remotely on a server and from what it seems, you're doing it right.
Storing videos on YouTube is not the best idea but definitely better then just storing them on your server - if you have the ability to upload multiple Youtube videos from lots of users and if Google API allows that - I'd go for this option.
In general I would store as little as possible on the device, apart from the image cache maybe. Nevertheless even the image cache sometimes grows to hundreds of MBs so you have to think about it as well.

Fetch images asynchronous from url in unity3d

I am making a game in which I need to integrate Facebook leader-board and facebook friends invitation like in subway surfer. I used official facebook sdk and got it done. But the approach I am following is not efficient.
My friend invite screen has its own UI so I could not use the default popup comes with facebook SDK.
I fetch all the friends list from graph api It provides me the list of all IDs of users . But I needed to get name and images of friends to show in a scroll list . I am fetching the images from url asynchronously but whenever I try to fetch the image my scroll list hangs up . here is my code
IEnumerator start ()
{
url ="http://profile.ak.fbcdn.net/hprofile-ak-prn2/t5/1116929_100003613987476_290892640_q.jpg";
WWW www = new WWW(url);
yield return www;
var texture = www.texture;
this.gameObject.GetComponent<UITexture>().mainTexture = texture;
}
I am using coroutines, but I dont know why my scroll hang up on scrolling if these are asynchronous ? The code is been taken form here . I have checked Threading but www can not be used in threads. I just want to smooth my scrollview which I made by using NGUI sdk during image fetching.
Problem 1 - How can I make smooth scrolling by asynchronous image download simultaneously.
Problem 2 - I am loading each image into UITexture of NGUI, which I instantiate at run time. But if one have 200 or above friends then my app's memory reach at apex point and eventually app crashes. Is there any other way to load large number of images so that they take reasonable memory .
Scroll is working smoothly during web call on editor but not on device (iOS). Why ?
Please guys help me to smooth my scroll view and memory issue. Any help shall highly be appreciated. Thakks :)
This is a common problem on devices for any list that has more than 50 items that include images. You need to control two things: initializing list items and downloading assets.
You do not need to load everything at once and display them. I would recommend breaking this down into three parts:
1. Store friend list data
Fetch all the user's Facebook friends and store it in a list. This does not include downloading the profile pictures, only the basic information and the URL of their profile picture. We will download the picture at a later step.
2. Pool list items
Don't create more than triple the list items you can display at any given time. While scrolling, you'll simply reuse the ones already created like so:
You should only need to do the third step in that picture only when the user has lifted his finger and the list has enough momentum to continue scrolling. Otherwise you should have enough items loaded in memory to not require this when the user simply drags the list.
When moving a list item either at the end or the beginning (depending on the direction of the scroll) you should load the friend's data. You still do not load profile pictures at this step.
3. Queuing image requests
You can use Unity's OnBecameVisible method to figure out when an item is currently visible. But generally you'll need a manager that keeps track of what items are visible at any given moment.
Every time the scroll list has no momentum and the user is not dragging it, you queue up requests to fetch the images for the items that are currently visible. This should be handled by a different manager that does the following:
Keeps N most recent profile pictures in memory to avoid loading them every time
Checks to see if the image is already downloaded by using LoadFromCacheOrDownload as Roberto suggested.
Makes sure that the item the request was made for is still visible before setting the texture (otherwise it keeps the image in memory)
Of course, this is very high level. There are many things to implement here and in many different ways. But I hope you get the idea.
I was thinking about this when I asked about starting many coroutines at the same time.
Well you just can't load them all at the same time and expect the app to run smoothly, the hardware is just not able to handle this.
You can made a loading screen or something similar where the user will have to wait to see/use the scroller (though I've never seen a game doing this for loading Facebook pictures) or you will have to give up in showing them all at the same time and create a pool of a small number of WWW connections that you can use at the same time, that is, limit the number of images being loaded at the same time, and only start loading a new image when one has finished.
Now one thing that can certainly speed things up - not in the first time that you run it, but subsequent runs - is to use WWW.LoadFromCacheOrDownload() instead of new WWW(). This method will store the pictures that were downloaded in the past and load them instead of redownloading. This is how every Unity game I've ever seen do integration with Facebook.

iOS App Development - Downloading large content using JSON

We have a Universal iOS app. We use JSON to download content into the app during the first launch.
The size of content being downloaded on iPad (due to large image sizes) is about 100MB and on iPhone (smaller images) 80MB.
It takes about 4-7 minutes to download all content over WiFi. On 3G it takes 7-10 minutes.
Images are large in size, text content is not so much.
Is there any way we could reduce the download time? I'm aware of JSON compression but not sure if it will help with images?
Any ideas?
Tx
Some of this information has been mentioned in various comments, but it's what I would have suggested anyway and I figured having an answer written up would be more useful, so here goes:
Instead of storing the location of each image in the JSON file and downloading them one at a time, store the images in zip files and download those. Any amount of compression you get from this is an improvement in your download time, and you can simply unzip the images once you've downloaded the zip files.
Store a reasonable amount of the images in the main bundle along with the app. In your case you clearly can't store them all there; you don't want to have a huge app, and since it's a recipe app I presume you'll be adding more recipes as you go along. It makes a lot more sense to be able to update and download recipes via the JSON than to have to push a new version of the app to the app store with each change. But there are some items that can be bundled with the app; ex. large background images, design elements that are constant and unlikely to change. Any image which won't be likely to need updating should be bundled with the main app; any savings on download time is an improvement.
Have some kind of interesting loading screen. This is very important since you're talking about 4-10 minute download times. That is a long time for a user. When engaging with an application, 30 seconds can even seem like a long time. You're going to be hard pressed to make me willing to sit there and wait for 10 minutes for the app to begin if nothing is happening during that time. Have creative vegetable characters move across the screen, include a little interactive puzzle or ingredients on the loading screen, something. Just give the user something to look at (or preferably something interactive to do) while they're waiting. Otherwise you're probably going to lose a lot of users during this download.
If you can make this work, it really is a good idea to only download items when necessary. For example if your recipe app is broken into "Salads", "Fish", "Chicken", "Desserts", etc., you could prompt the user to download the recipe information for each category the first time they click on it. The great thing about this is that it breaks up the time the user has to spend waiting on the download; let's say you have 10 recipe categories, now the time the user has to wait all at once has been decreased from 4-10 minutes to 30 seconds-1 minute. That is a huge difference. I'll wait 1 minute for the Dessert recipes (still give them something to do!) much more readily than I'll wait 10 minutes for the whole app.
4b. You mentioned not being able to access new content while offline, which is a valid concern. To address this you could have a prompt the first time the app loads: This application contains hundreds of exciting recipes and delicious images. It can take several minutes to download all this yummy information. You can download all the content now, or proceed to the app and download recipes by category when you wish to view them. Please note that this will require an internet connection. And the buttons could say something like Download Now and Proceed to App. Obviously you can play with the wording to your heart's content, but the idea is sound. You've informed the user that there might be a significant download time, so at least they're forewarned, and they can make their own decision about how to use your app.
However you decide to proceed, break up the content you download into logical categories for the zip files. For example, "Desserts.zip", "Salads.zip", etc. That way even if you don't decide to let the user download on-demand now, you've set up a structure that is open to change later on.

Is it good for an iPad application to have everything in local?

I develop an iPad application for a company. They want to use the application to show media, like pdf docs, pictures, video. They want one application for everything.
So I use a TabBar Application, each TabBar display a media, like pictures gallery, video gallery. The application is pretty big. And now the application is running slowly. The display of pdf is not smooth, the swich of tab takes time. I use the local data because I can use internet for the application, it needs to works everywhere without wifi.
So my question, is it a good idea to put everything in the same application? I add all my media in the xcode project.
Is the iPad good for displaying video, pdfs, pictures in the same application ? I want something smooth, but to much data for the memory kills my application. What ways I need to take ? Do you have ideas ?
It sounds like you are not purging media from memory when it is no longer used.
Make sure to release media related objects that are not immediately in use. Images in particular eat memory very quickly because all the data associated with an image has to been in memory. Unlike a PDF or audio file which can be read in as needed.
Users will expect and tolerate some slight delay switching from media type to media type because they experience that will all other apps and other forms of software. What they don't tolerate is slow performance while actively using a piece of media e.g. slow scrolling in a PDF file.

Resources