Objective C Data Caching on iOS - objective-c

I am pulling data from an API and then building out my data objects with it. I want to cache this data for the future. I have been storing the string from the api in NSUserDefaults and then re-parsing it each time the app loads. This works, but it really seems like the wrong way to go about it.
How can I do this?

Have you noticed the NSCache?
An NSCache object is a mutable collection that stores key-value pairs, similar to an NSDictionary object. The NSCache class provides a programmatic interface to adding and removing objects and setting eviction policies based on the total cost and number of objects in the cache...

Personally I'm quite fond of the EGOCache classes, I use them quite a lot in my projects:
https://github.com/enormego/EGOCache
The classes are easy to use, I used to have my own classes with a similar design, but these are just more well-rounded, so I decided to stick with them (don't wanna reinvent the wheel).

There are many different solutions to this problem and there is no "right" way to do it. A few popular options are:
Core Data - Apple's framework for persistence. Very performant, but more difficult.
SQLite - Fast and flexible, but bare bones.
Plists - Basically writing a file to disk, you have to read and write manually.
NSUserDefaults - The lightest weight "key-value" option.
I would encourage you to read up on all four and see which one works best for you.

I vote Core Data

What type of data? If its text/string bases SQLLite would probably be the best.

I'd store the computed/parsed data in either a Core Data store, or in NSData flat files in your application's Documents directory. You're correct that storing that in NSUserDefaults and then re parsing feels a little overkill.

Related

Nested NSMutableDictionary efficiency and alternatives

I need to store big amounts of nested strings and access all the data using some simple format (for example, 'my.data.object.path').
For example, if I've got the following structure:
- object1
- object2
-- nested1
-- nested2
--- nestednested1
I need to check, for example, if object2.nested2.nestednested1 exists. Sometimes I also have to check whether object2.nested2 and object2 also exist.
Is it efficient to use nested NSMutableDictionary objects, or should I write some more efficient data storage model from scratch? Maybe there are ready-to-use 3rd-party solutions to this problem that you could suggest.
I was also thinking about storing all my.variable.path paths in a single NSMutableDictionary, so I can set variables simply doing [storage setObject:object forKey:#"my.variable.path"] and extract them by defining a custom method that split incoming path by dot and try to find the shortest chunk of path.
I would seriously consider using Core Data for this.
It works great with large amounts of data.
It is very memory efficient, even with very large amounts of data since it loads it as
needed.
You can access it exactly like in your example.
It is built-in mature technology.
The main Apple document covering it is the Core Data Programming Guide.
They also have Core Data Tutorial for iOS which is a little shorter and gets you started.
There are also lots of non-Apple tutorials available on the web. One of my favorites is by Ran Wenderlich: Core Data on iOS 5 Tutorial: Getting Started. He also has other tutorials on Core Data linked from that article and here.
Dictionary are hash mapped, it is faster than Arrays.
And what level it is nested you can access it by [dict valueForKeyPath.#"key1.key2...."]
Upto 3 levels it fine, but if you are going beyond that then you can think of designing a Class structure to solve this problem.

Your Second iOS App - Enable Persistent Master List

So i'm following the ios tutorial here
http://developer.apple.com/library/ios/documentation/iPhone/Conceptual/SecondiOSAppTutorial/Introduction/Introduction.html#//apple_ref/doc/uid/TP40011318-CH1-SW1
The data for the tableview is a custom class containing just strings and dates.
Here is what it looks like
http://developer.apple.com/library/ios/#documentation/iPhone/Conceptual/SecondiOSAppTutorial/DesigningDataModel/DesigningDataModel.html
Can anyone suggest how to save this to data between launches of the app?
What about making the app Document based .. i.e. using UIDocument?
You could use NSCoding to store such simple data. You could probably even use NSUserDefaults but I wouldn't recommend it. Core Data is really the way to go unless you know you'll never need anything slightly more complex.
Check out this guide on how to persist simple data using NSCoding from www.raywenderlich.com - a really good tutorial site for people beginning iOS development.
You could use NSCoding or NSUserDefaults.
But for any real application that has a lot more than sample data you'll be looking at something like Core Data eventually.
From your comments I see that you think it's overkill for just a couple of fields. However, this is an ideal time to learn about and practice setting up a Core Data model and connecting it to a table view with a Fetched results controller.

Storing UIImage as Transformable attribute in Core Data

I am currently working on an app in which I want to store a UIImage in one of my Core Data entities. I have read that in iOS 5 UIImage now conforms to a protocol called NSCoding, so conversion methods from NSData are no longer necessary. I have set my image attribute to Transformable, and my program works wonderfully when I retrieve the image.
Is this a safe and secure method to store a UIImage that will allow for future below 30 second migrations? Will it be good performance-wise? I have also read about the Binary Data attribute type, that allows files to be stored in the file system, rather than the database. If this is a better alternative, how would one implement it?
Migration time depends on the entire database schema and size, not just storing a UIImage. No one can answer that question.
Performance is relative. If you store it externally, it will generally be better performance-wise, because it's not in the database itself, but there are lots of other performance issues, like managing the fault, especially if you store it as a direct attribute as opposed to a relationship. Also, it depends on your usage. No single solution is best for all circumstance.
You must profile your application use cases, and make the decisions that best serve the performance characteristics of your application.
For any non-trivial binary data, you should indeed let Core Data manage that as external data. It's simple. In the data model GUI, check the box that says "Store in External Record File."
Sorry, I didn't notice you said that you were already perfectly aware of how to encode images. I would not recommend storing them in the database, but good luck.
Previously: Storing UIImage in Core Data with the new External Storage flag
The comments on that thread about bugs suggest it is still probably a safe idea to just store images on the filesystem yourself.

Should I use SQLite to add this feature?

I need your advise on this, I'm currently developing a kinda family application.(Everything relates to the family)
I would like to add something similar to a family tree or the family members. (Using Table view) and each member/element on the list will have its own "view" containing a 50 words biography about him and his photo.
Since, I'm still new to iOS development and I still haven't worked with SQLite yet. Do you guys think SQLite is the best for this job? How about the photos. Is there a way to put a thumbnail photo for each member?
SQLite does this well, though Core Data is generally considered the preferred iOS technology. There are a few situations where I might advise using SQLite over Core Data, but you haven't outlined any app requirements that would make me lean that direction.
If you do your own SQLite, though, I'd suggest you use something like FMDB, so you spare yourself the hassles of writing SQLite code.
And, as I mentioned in the comment of another answer to this question, regarding images in Core Data or SQLite, you face a significant performance hit for that. If you're dealing with small images (e.g. thumbnails), it's fine, but if you're dealing with a lot of large images, you really might want to consider storing them in some directory structure under the Documents folder (and then store relative path names in your database). It not architecturally elegant to take the images out of the database and use the Documents folder, but for performance reasons you might want to do precisely that.
No. I would use CoreData for this. CoreData gives you the graphical modelling tools to build an object model and handles all the tedious housekeeping required to persist your object graph to disk.
The photos you would store as conventional files on disk and be modelled by a CoreData object that maintains a reference (URI or file path) to the photo.
I would use CoreData for this, it boils down to an SQLite database, but Apple have added their own wrapper round the SQLite database, making it really simple to use.
There are a number sample apps on the Developer Site as well as numerous Tuts available just by searching the phrase "CoreData example" in google, the link here is ro Raywenderlich which is a good place to start. I think once you go through this blog you'll be using CoreData more and more when you need to store things like this.
With regards to the thumbnail storage I would store those on the device and save the path to the file in the Database.
Yes you can use SQLite for this; in fact it's ideal for holding a family tree given its relational nature.
The photo data can be serialised into a byte stream (NSData *) and stored in a column as a blob.
A database has the huge pro, that you can keep everything stored at one place.
You could (not that I recommend) also use a folder-structure to specify the data like /images/, /words/, /people/ and use the same name for everyone throughout the folders (tim.jpg, tim.txt, tim.dat )
Or use a small database to store everything in different tables all with relation to your "family(_members)" table.
You can also store images in a database, mostly as a blob (or base64 encoded or or or... yuck)
I don't know how well iOS stuff handles those database types of SQLite but you should be better of using a database for that.
You have a number of options here.
If you are storing all of the info within the application itself (ie. the details aren't being fetched from the web somewhere), SQLite (as a CoreData backend) would probably be a good idea. Read up on using CoreData so that you don't end up reinventing the wheel, and so that your implementation provides a smooth scrolling experience that iPhone users expect.
The photos, however, need a different means of storage/retrieval.
A common technique is to implement a 2-level cache system. What this would entail is storing the pictures in individual files, but keeping some of them in-memory after they are retrieved for speed. You could then have a class that looks something like the following:
#interface ThumbnailManager : NSObject
{
id<ImageCache> _imageCache; // You make this.
}
- (UIImage *)imageForFamilyMemberWithName:(NSString *)name;
#end
That's similar to something I would do in your position.
Good luck!

Objective-C best choice for saving data

I'm currently looking for the best way to save data in my iPhone application; data that will persist between opening and closing of the application. I've looked into archiving using a NSKeyedArchiver and I have been successful in making it work. However, I've noticed that if I try to save multiple objects, they keep getting overwritten every time I save. (Essentially, the user will be able to create a list of things he/she wants, save the list, create a few more lists, save them all, then be able to go back and select any of those lists to load at a future date.)
I've heard about SQLite, Core Data, or using .plists to store multiple arrays of data that will persist over time. Could someone point me in the best direction to save my data? Thanks!
Core Data is very powerful and easy to use once you get over the initial learning curve. here's a good tutorial to get you started - clicky
As an easy and powerful alternative to CoreData, look into ActiveRecord for Objective-C. https://github.com/aptiva/activerecord
I'd go with NSKeyedArchiver. Sounds like the problem is you're not organizing your graph properly.
You technically have a list of lists, but you're only saving the inner-nested list.
You should be added the list to a "super" list, and then archiving the super-list.
CoreData / SQL seems a bit much from what you described.
Also you can try this framework. It's very simple and easy to use.
It's based on ActiveRecord pattern and allow to use migrations, relationships, validations, and more.
It use sqlite3 only, without CoreData, but you don't need to use raw sql or create tables manually.
Just describe your iActiveRecord and enjoy.
You want to check out this tutorial by Ray Wenderlich on Getting started with CoreData. Its short and goes over the basics of CoreData.
Essentially you only want to look at plists if you have a small amount of data to store. A simple list of settings or preferences. Anything larger than that and it breaks down specifically around performance. There is a great video on iTunesU where the developers at LinkedIn describe their performance metrics between plists and CoreData.
Archiving works, but is going to be a lot of work to store and retrieve your data, as well as put the performance challenge on your back. So I wouldn't go there. I would use CoreData. Its extremely simple to get started with and if you understand the objects in this stack overflow question then you know everything you need to get going.