core data, storing images in a dictionary - ios

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.

Related

Image caching best practice for unique identifier

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?

efficient storage and retrieval of large set of objects in dictionaries/arrays

I am creating a data source from a user's complete set of photos stored on the device (which may number in the thousands).
For each asset, I need:
URL
latitude
longitude
timestamp
When the view loads, I will enumerate all of the assets and store these 4 pieces of data for each asset. I am wondering if there are significant differences among the options for arranging all of this data. For example:
Create 1 array, with each object in the array containing a dictionary with 4 key-value pairs.
vs.
Create 1 array, containing just the URL strings. Create 3 additional dictionaries, 1 mapping each URL string to a latitude, 1 mapping each URL string to a longitude, and 1 mapping each URL string to a timestamp.
vs.
Same as #1, but instead of adding dictionaries to the array, add instances of a custom class subclassed from NSObject and containing 4 properties.
Are there significant differences in the time required to create or read from these collections (assuming thousands of objects)? Thanks.
There are lots of ways to do this, but the simplest that would save you time and would have a very low overhead would be to create a class that holds the four properties you want to create and put them in a dictionary. Making your own object to hold these pieces of information rather than rigging together a couple arrays or dictionaries will allow for more flexibility in the future.
As you enumerate through the photos, set the objects in the dictionary with the timestamp as the key (or whatever unique property you want). You can sort the keys in O(n*(log n)) and access entries in O(1) time. Then you have a sorted list of all images, it's quick, scalable, and you can easily add more properties in the future.

Best way to represent un-ordered data in a plist

I'm making a plist to hold genre synonyms. The list of synonyms for a given genre doesn't have any inherent order to it.
Should I use an array (which implies an order that doesn't exist) or a dictionary (which implies there's a corresponding value for each key, which doesn't exist).
Simply put--to store an unordered set in a plist, how should I represent it and why?
(To clarify: If there were a Set data structure in the plist editor, I would use that, but I only have Array and Dictionary to choose from.)
More details: I'm going to be looking up by the primary representation of the genre, thus the outer data structure in the plist has to be a dictionary.
But then for the synonyms, the only operation necessary is to enumerate them using a block.
So either an array or a dictionary will do. However, I'm concerned that using an array will imply an order that doesn't have any semantic meaning. On the other hand, is it a common occurrence to have dictionaries in plists that don't have a corresponding value?
Editing again to respond to Josh's comments:
I like your idea of converting into an NSSet after reading in the plist. However, I could still do that with a dictionary, right? So not sure why an array is the obvious choice.
If someone else edits the plist, they might think there's a meaning to the order, when in reality, the ordering is arbitrary.
Surprised no-one has defended using a dictionary instead of an array. Is there a reason a dictionary shouldn't be used in a plist for this purpose?
If you don't care about order, then the arbitrary order you get from building an array is equivalent to the arbitrary order you'd get by using a set. You can also very easily convert an array in a plist to an NSSet after reading it back: +[NSSet setWithArray:]
So use an array.
I would just use an array, since you say there's no corresponding key for a dictionary entry.
At the same time, if you're typing in a large number of entries into plist files (www), your fingers may get tired from dealing with the raw XML or plist editor stuff. You might want to consider a different way to save your synonyms?
Use an NSArray if lookup by item is not needed. If lookup is needed use an NSDictionary.

What is a good way to store a persistent array?

I have an NSMutableArray of objects that I would like to persist between user sessions. Each object has an NSInteger property, and I would like to be able to access all of the objects for calculations using that property (averages, mins, maxes, etc.)
Would it be better to store that array into a Core Data database or just store my objects individually into the database?
EDIT: The array should hold no more than 1,000 items.
Depends on the size. If it's simple just archive the array to a file
Edited to add
If all you want to persist is an array you don't need to use the archiver methods, you can do it directly.
Imagine you have a file URL in your app's Documents directory called persistentURL which you want to use to save and read your array from.
All you need to do to persist the array is:
[yourArray writeToURL:persistentURL atomically:YES];
And when you want to read the data back into an array it's as simple as:
yourArray = [NSArray arrayWithContentsOfURL:persistentURL];
You can use this method here because the array contains only NSNumbers which are property list objects (i.e. objects that can be put directly into a plist).
NSArray and NSMutableArray can't contain integers directly. It has to contain NSNumber objects.
Anyway, I'd just use NSCoding. Try the methods archiveRootObject:toFile: (which writes directly to a file) or archivedDataWithRootObject (which converts the content to a byte-stream in NSData).
For <=1000 items it should be fast enough.
If you're reading and writing the array enough, you might want to consider using a malloc'ed C array of "long"s, and saving that as bytes to a file. That would be faster, and you could read/write values to your C array easily, instead of having to do object replacement. On the other hand resizing the array or inserting values is a pain with a C array, and you also have to be aware of data size and byte ordering issues if you will ever transfer this data between devices.
Edit: I just wrote a little test, and writing an NSArray of 1,000 NSNumbers to a file with archiveRootObject:toFile: takes about 0.0038 seconds on on old iPhone 4 I have around for testing. That's the slowest machine that supports iOS 7, and it's 3.8 THOUSANDTHS of a second, to write 1,000 items. So writing an array of 10,000 items should take 3.8 hundredths of a second or less.
Unless you are reading and writing this array many times a second in a loop, using archiveRootObject:toFile: is plenty fast enough.
Personally, I would use the following to store that array:
[[NSUserDefaults standardUserDefaults] setObject:myArray ForKey:#"myArray"]
and retrieve it anywhere in the app:
NSMutableArray *myArray = [[[NSUserDefaults standardUserDefaults] objectForKey:#"myArray"] mutableCopy];
That seems to me to be the easiest way to persist that data. You can store the mutable array in NSUser defaults, and I believe you'll need to create a mutable copy of it when you retrieve it later on to be able to continue to make changes to it.

Nsdictionary as a data type

Would nsdictionary be a good data type to use for storing long string values as values and names of those descriptions for keys? Or would a different data type be more effective? I am using it for animals, and having and array hold all the data then using a dictionary to point to the name and description of the animal. I'm just curious if this is used for smaller data like states and capitals
Or should I just use a #Define #"rhino description"
[Animal animalObj:#"rhino" location:#"the water" description:[[self setGenericAnimals] valueForKey:#"Rhino"]]
NSDictionary is OK for this. Whats great about using NSDictionary is you can save your data as JSON in a sperate file and then serialzie it into a NSDictonary when you need it. This would make it easier for you to manage all your data and it seperates it from your application.
this is a good start on how to convert JSON into a NSdictionary.
http://www.raywenderlich.com/5492/working-with-json-in-ios-5
Remember though that the entire NSDictionary must fit into memory so if your going to have thousands of strings you might want to separate that into different JSON files and then serialize them into Dictionaries when you need them.
Another thing to remember is that if you want to do simple comparisons and sorting options on objects you are better using CoreData as this allows you to store lots of strings and easily access them.

Resources