How do I test PHImageResultIsInCloudKey? - ios

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 :)

Related

Handling cache right?

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?

Firebase Storage: How to reduce requests? (iOS)

I'm developing a chat app with Firebase. Am currently still in development phase.
Profile pictures of test users are uploaded to Firebase Storage, and are downloaded in the home screen (with all the pictures). I realized that with that I very quickly used up storage download requests (easily hit 3,000 requests in one night, and hit the free plan quota!).
What are some best practices I could use to minimize download requests? Just to be sure I'm doing it right - I'm sending a GET request to the Firebase Storage url directly: https://firebasestorage.googleapis.com/... to download the image. Is that the right way to do it?
Two suggestions that might help:
Cache your images! If you keep requesting the same images over and over again over the network, that's going to use up your quota pretty fast. Not to mention your user's battery and network traffic. After you retrieve an image from the network, save it locally, and then the next time you need an image, look for it locally before you make another network request. Or consider using a library like PINRemoteImage that does most of the work for you. (Both on the retrieving as well as the caching side)
Consider uploading smaller versions of your image if you think you might be using them often. If your chat app, for instance, saves profile pictures as 1024x768 images, but then spend most of its time showing them as 66x50 thumbnails, you're probably downloading a lot of data you don't need. Consider saving both the original image and a thumbnail, and then grabbing the larger one only if you need it.
Hope that helps...

Delete unused persistent data without reference

I have an app which communicates with a server. In this app I have a tableview in which I display several people from my company (their first and last name and their profile image).
Every time the tableview opens or needs to refresh, I fetch the user list from my server. These users will all have an image_name, which I try to look up in an array on the app itself. If I can't find it there, I load it from the documents dir, if I can't find it there either I download it from my server and save in locally on the device to prevent future downloads.
This works very well and it's a very easy way to manage the users and their images, it also makes sure that I download an image only once if several users have the same image (e.g. the company logo when they haven't uploaded an image yet).
The problem is that I don't keep a reference to these users so the app has no clue which user uses which image OR even if an image is still in use.
So when person A has image X it will be downloaded to the iPhone. If user A then changes his image to Y, the app will download and display image Y correctly. However, image X will never get deleted from the persistent data.
I ask you, the stackoverflow community, what's the best way to handle this?
Should I start keeping a reference to my users so I can also keep a reference to the old image?
Is there any way to find the timestamp of the last time and image was read from the documents dir?
Should I store the image names in coreData and all the references to them? (some kind of custom ARC logic)
...
At some point in time you have the list of used images, at this point in time you also have a list of images saved to disk. Once per day you can take this information and, on a background thread, do a comparison of the used and saved and delete them. This shouldn't require any additional data storage.
If you wanted to allow images to hang around for a while after they stop being used you can 'touch' the file (update the fileModificationDate) each time you use the file and then later you can check the modification dates of all images and delete on that basis.
You could add a prefix to the image that you download and when you fetch images, check all images in persistent storage for this prefix and then remove if there are any. You should only need to delete (maximum) one image every time your client fetches, which wouldn't be too heavy on the client.

How to download and store images to not be cleared by device later?

I have an application which downloads its product data(descipttions and images) from server and stores them localy to be available offline. For product images I'm using forge.file.cacheURL which works great but on my iPAD, this cache is being cleared during the day when I work with another apps. This causes my application to have only descipription texts available without images and user must connect to internet and synchronize again what is quite annoying. Is there a better way how to implement this scenario?
Have you tried to use the forge.prefs module for this purpose? It allows you so persistantly save key-value-pairs locally (much like HTML5 localstorage). Read more about the exact syntax in Trigger.io's official API documentation.
I'm not quite sure whether its possible to save images with this method, but you could easily transform your images into strings and vice-versa. Check out the second chapter of this post by Robert Nyman on how to save images in localStorage.

Best way to collect data for an iPad app that also have an offline mode

My client states in an iPad app brief that the data (i.e. products and images) must be taken from an online source and saved. However, the app must also have an offline mode which shows this same data from when the app was previously online for times when internet access is not available (kind of like an offline reader). What would be the best way to tackle this? Any help greatly appreciated.
Download the data when the device is online and store it locally using whatever mechanism seems most appropriate (SQLite, Core Data, property lists, your own file format, etc.). Use this cached data when offline, and when online too unless it has changed. Create some mechanism that you can use to detect and download updates (preferably just the changes) when online.
This will be a big help for your users not just when they're offline, but online too. 3G data plans for the iPad are usually limited, so the better you can avoid repeat downloads of large resources like images, the better for your users.

Resources