Image caching best practice for unique identifier - ios

I am trying to build an app where I download a list of images from different URLs into a collection view. All these images are stored inside a cache with max age and cache limit. I am storing the URL as the key for each image so that I can check if the image already exists when downloading it again and if yes, check the max age, but I have been told that storing URLs as ID is bad practice. Any suggestions on how I could save these images and retrieve their details when needed?

So to be clear were thinking a good way to store info about an image is instead of having an object like this :
"some_url_as_the_key":{ // details about the image }
we could have.
"number_of_bytes_of_the_image_as_key":{ //detail about the image }
Im trying to do the same and need to store the meta data bout each image in a dictionary. Which of the above would be best. I can see an issue in as much as two images could theoretically have the same number of bytes, though 1) this is unlikely, and 2) would possibly be a faster look up when searching for the meta data about an image that i need to store. I.e. a key of '12312423' (number of bytes), vs a long url like "https://www.lindofinasdoifnosidnf.sdfsdfnsdf/dfsdf' would be faster i guess.
Thoughts?

Related

Will I incur excessive costs doing something like the following with firebase keys?

I am using firebase realtime DB for my iOS app. Something I do very often is store some info in a nodes key for easy access, and to solve some other problems in my code. But I have been wondering if I will be charged more for doing something like that, instead of just storing the data inside the node.
For example I do the following (store the postID And UID in the key):
Timeline/uid/someUID:postID/ Other data here...
Would I be causing myself to pay extra? Would it be cheaper to just use a randomID? Are there any other considerations?
The short answer is no, look here the limit the number of conections and the amount of data stored, since id is string randomly generated if you set another id is not a diference sinc is string and would not make a huge diference, and about other data added unless is to much data a string is not make you cost extra, in free plan only 100 conections allow simultaneosly and 10GB per month of donwloaded data, and 1gb of DB, unles every node and have a lot node then there is not difference

How to use NSCache appropriately in iOS application?

I am building an application and want to use NSCache to store data for caching.
There will be approx 5 API for which I need to cache data. Should I user NSCache? I did research for NSCache but I have some doubts regarding this.
I did go through below link.
https://developer.apple.com/library/content/documentation/Performance/Conceptual/ManagingMemory/Articles/CachingandPurgeableMemory.html
I found some interesting things there.
NSCache provides two other useful "limit" features: limiting the number of cached elements and limiting the total cost of all elements in the cache. To limit the number of elements that the cache is allowed to have, call the method setCountLimit:. For example, if you try to add 11 items to a cache whose countLimit is set to 10, the cache could automatically discard one of the elements.
If we set limit to 10 and if we try to add 11th item then which particular item it will discard that is 1st one or 10th one? Or it can be a random item.
If I want to store 5 different NSCache object for all APIs then how can I do it?
I should make 5 different NSCache objects or I should store 5 different dictionary in single NSCache object?
Please let me know the best way to deal with it.
NSCache works basically as an NSMutableDictionary, the main difference is that even if is mutable is thread safe (usually mutable NSFoundation objects are not thread safe). So you get and set objects using keys.
Yes, the documentation is not clear, but I remember (and it makes sense) that is written that you should always detect if an object is cache and if not reload it from your primary source or manage that particular case. So it is not very important which one is removed, just make sure that at some point an object can not be there anymore and you are managing that situation.
I usually create different caches based on different context, but most of the time one would suffice.
I have few advices:
Your answer is tagged as Swift, thus pay attention that NSCache (in swift 2, don't know in 3) works only with objects and not struct or enumerations (value types unless thay can be bridged).
Remember that http protocol has its own cache system and communication, do not reinvent the wheel

How to store images into Neo4j

I came across a scenario i.e, Each and every node is to represent with an image . so i have to store image into neo4j. please healp me out with your views on it.
You have several options:
As #Christophe Willemsen suggested you, save the image on disk or on a web site and reference it using a URL.
Save it in byte[] array as a property.
Save the image in base64 using a Data URI (as String).
Of course option 2 and 3 are not recommendable if the images are very large. Though you could save a thumbnail in the database and the full image on file system.
You should save some metadata too in properties, like type, size, location etc.. to improve searches in the database.
According to the Neo4j community:
Don't add large blobs of data, e.g. base64, to the graph as property values. This is one of the few anti-use-cases for graph databases.
Store the binary information somewhere, e.g. AWS S3, and have a node representing that photo or video. That node contains the S3 URL as reference and potentially some meta-data as well (width, height, quality, codec).
Use relationships to amend information like tagging, comments, ownership and permissions.
Kudos to Stefan Armbruster (Neo4j Staff) for the info.

core data, storing images in a dictionary

I have an app that feature "pages". Each page can have n number of images, depending on user preference. To store the images and associate the image with the correct view etc, I am building a dictionary for each image, then storing that dictionary in an array of image dictionaries, which I save to core data as binary data. I am storing the image itself as an object in the dictionary, like below. Is this an efficient and safe way to do this? Seems to work ok...
imageDictionay = [NSMutableDictionary dictionaryWithObjectsAndKeys:image, #"image", imageTag, #"tag", imageTransformString, #"transform", nil];
That way will certainly work, but I would personally create another entity for ImageInfo like so:
If you are going to have a dictionary with the same three keys, it makes more sense to me to have an entity with those three attributes.
Also, if you are really worried about performance, you could also write the image to disk and just put a string in Core Data to tell you where the image is stored.

What's the effect of cache to NSFetchedResultsController

I read the doc of course, but I don't quite get the meaning of "setting up any sections and ordering the contents".
Don't these kinds of information come form data base?
Does it mean NSFetchedResultsController needs some other kinds of indices itself beside data base indices?
What's really going on when NSFetchedResultsController is setting up a cache?
Is cache useful for static data only? If my data update frequently, should I use cache or not?
How can I profile the performance of cache? I tried cache, but couldn't see any performance improvement. I timed -performFetch: but saw a time increase from 0.018s(without cache) to 0.023s(with cache). I also timed -objectAtIndexPath: and only a time decrease from 0.000030(without cache) to 0.000029(with catch).
In other words, I want to know when cache does(or does not) improves performance and why.
As #Marcus pointed below, "500 Entries is tiny. Core Data can handle that without a human noticeable lag. Caching is used when you have tens of thousands of records." So I think there are few apps that would benefit from using cache.
The cache for the NSFetchedResultsController is a kind of short cut. It is a cache of the last results from the NSFetchRequest. It is not the entire data but enough data for the NSFetchedResultsController to display its results quickly; very quickly.
It is a "copy" of the data from the database that is serialized to disk in a format that is easily consumed by the NSFetchedResultsController on its next instantiation.
To look at it another way, it is the last results flash frozen to disk.
From the documentation of NSFetchedResultsController:
Where possible, a controller uses a cache to avoid the need to repeat work performed in setting up any sections and ordering the contents
To take advantage of the cache you should use sectioning or ordering of your data.
So if in initWithFetchRequest:managedObjectContext:sectionNameKeyPath:cacheName: you set the sectionNameKeyPath to nil you probably won't notice any performance gain.
From the documentation
The Cache Where possible, a controller uses a cache to avoid the need
to repeat work performed in setting up any sections and ordering the
contents. The cache is maintained across launches of your application.
When you initialize an instance of NSFetchedResultsController, you
typically specify a cache name. (If you do not specify a cache name,
the controller does not cache data.) When you create a controller, it
looks for an existing cache with the given name:
If the controller can’t find an appropriate cache, it calculates the
required sections and the order of objects within sections. It then
writes this information to disk.
If it finds a cache with the same name, the controller tests the cache
to determine whether its contents are still valid. The controller
compares the current entity name, entity version hash, sort
descriptors, and section key-path with those stored in the cache, as
well as the modification date of the cached information file and the
persistent store file.
If the cache is consistent with the current information, the
controller reuses the previously-computed information.
If the cache is not consistent with the current information, then the
required information is recomputed, and the cache updated.
Any time the section and ordering information change, the cache is
updated.
If you have multiple fetched results controllers with different
configurations (different sort descriptors and so on), you must give
each a different cache name.
You can purge a cache using deleteCache(withName:).

Resources