Best way to cache an NSArray of text/dictionaries and have it useable across the entire app? - xcode

I am making a request for an array of perhaps 10-100 objects, all of which are JSON objects that I parse into NSDictionary's. I want to cache this and use this data across the entire application. Is NSCache useful for this or is it better to use NSUserDefaults or what is actually the most accepted way of persisting data across an entire app? CoreData? I'm a iOS newb and don't have too much experience in this.

What you are looking for is a way to access data across your app. This is typically the role a Model plays in MVC.
CoreData and NSUserDefaults are ways to save data so it is not lost when your app closes or is quit. They can be parts of a Model, but do not help in having that data be accessible throughout your app.
If you want an object that stores data and can be accessed anywhere in your code, you are probably looking for a Singleton.
As this excellent Stack Overflow answer explains:
Use a singleton class, I use them all the time for global data manager classes that need to be accessible from anywhere inside the application.
The author provides some sample code you might find helpful.
This would allow you to create a simple object accessible throughout your program that has your NSDictionaries. Because it is a singleton, other classes in your program can easily access it - meaning they can also easily access the NSDictionaries you've stored in it.
If you do decide you want to save data, that singleton object would also be an ideal location to write any load and save code.
Good luck!
Other good resources are:
Wikipedia's Entry on Singeltons
What Should My Objective C Singleton Look Like?
Singeltons and ARC/GCD

Related

What's the best practice for NSPersistentContainer newBackgroundContext?

I'm familiarizing myself with NSPersistentContainer. I wonder if it's better to spawn an instance of the private context with newBackgroundContext every time I need to insert/fetch some entities in the background or create one private context, keep it and use for all background tasks through the lifetime of the app.
The documentation also offers convenience method performBackgroundTask. Just trying to figure out the best practice here.
I generally recommend one of two approaches. (There are other setups that work, but these are two that I have used, and tested and would recommend.)
The Simple Way
You read from the viewContext and you write to the viewContext and only use the main thread. This is the simplest approach and avoid a lot of the multithread issues that are common with core-data. The problem is that the disk access is happening on the main thread and if you are doing a lot of it it could slow down your app.
This approach is suitable for small lightweight application. Any app that has less than a few thousand total entities and no bulk changes at once would be a good candidate for this. A simple todo list, would be a good example.
The Complex Way
The complex way is to only read from the viewContext on the main thread and do all your writing using performBackgroundTask inside a serial queue. Every block inside the performBackgroundTask refetches any managedObjects that it needs (using objectIds) and all managedObjects that it creates are discarded at the end of the block. Each performBackgroundTask is transactional and saveContext is called at end of the block. A fuller description can be found here: NSPersistentContainer concurrency for saving to core data
This is a robust and functional core-data setup that can manage data at any reasonable scale.
The problem is that you much always make sure that the managedObjects are from the context you expect and are accessed on the correct thread. You also need a serial queue to make sure you don't get write conflicts. And you often need to use fetchedResultsController to make sure entities are not deleted while you are holding pointers to them.

How to get Core Data to make only one instance of entity of type

So. Before I get singleton pattern hate on this message hear me out. I'd love to hear ideas. I'm making a program that I think I need to use core data for, because later I want the status of some variables to be easily accessible from OS X, and multiple iOS devices.
What I'm making is an OS X program that will control phidgets (phidgets.com) to control and listen for status changes in real world objects. Example: whether a motor is turned on or not. Turn a motor on and off. Turn on status lights, etc.
I originally thought I'd just make global variables that I change, poll and manipulate in order to have a central status board for the logic of the program to work off of. But, because of the engineering that is put into core data every year by apple, I am assuming making this work with core data will allow me to more easily have options to sync this later with iOS devices that could control or monitor the said status' remotely.
Is there a nifty way you can imagine to:
-startup the program, confirm there is only one entity of type "SystemStatus", if there isn't one, make one. is there is one, we continue and are able to let the program update it's attributes with status of the real world objects it's controlling.
using core data was something I thought of also, because it will allow me a place to persist stored history of data gathered too. Example: motor bearing temperature over time.
If you ensure that access to this object is done through your API, Core Data becomes an implementation detail behind the getter method of the singleton object. There are no facilities in Core Data to tell it to create only one object, but if you ensure access to the object is done through a wrapper of your own, you can fetch it on demand and if it doesn't exist, you can insert it, save, and pass it to the caller.
An important thing to consider when using Core Data objects is multithreading. Passing the same object to multiple threads is very error-prone and requires locking mechanisms (or use of Apple's block-based API). This is not very straightforward for what you describe. Consider either a wrapper object which uses Core Data objects internally (wraps access to properties in block-based API) or using a different approach than Core Data.

How can I hold common runtime data in cocoa app?

I am new to cocoa and mac os x development.
Different components of my app use a particular location to store data etc, The location is determined at the start of the app. For example a subdirectory directory in the user's home directory , temp directory of the system etc and similar runtime information that is used by different classes in my cocoa app. This information should be determined at the start of the app once and reused later.
Every component should be able to access a central component to get this information rather than each one calculating over and over again.
Does cocoa provide some place to hold this data ? or Do we create singleton object ? any ideas ?
A common pattern for accessing shared model resources is a through a singleton model controller class, like you wrote. Here's how I manage creating/accessing singletons:
+ (id)sharedInstance {
static dispatch_once_t once;
static SomeModelControllerClass * sharedInstance;
dispatch_once(&once, ^ { sharedInstance = [[self alloc] init]; });
return sharedInstance;
}
The function dispatch_once guarantees that a given block of code identified by the dispatch_once_t token "once" is only executed once.
The other, more important, question is how to create/store the data that your model controller will manage. There a couple of options:
Keep it all in memory If you have a relatively small amount of data that can be held in memory all at once, and regenerated with ease on each app launch, then this is the simplest way. It is probably not a good user experience though.
NSCoding Have your model objects implement the NSCoding protocol methods (init/encode withCoder). Your model controller will be responsible for writing/reading your model stack to /from disk at appropriate times (preferably on a background thread). This technique makes sure your user sees some data immediately upon launch, but it requires that all data be held in memory after it's read from disk. It's a good technique for an app like Twitter, and indeed they used this technique for many years.
Core Data Core Data is a great choice for "shoebox" style apps with lots of data that needs to be stored locally and is too large to keep in memory all at once. It comes with a big learning curve and lots of boilerplate, so I only recommend this if you can't keep all your model objects in memory at once.
Custom Storage There are many third-party frameworks for doing what Core Data does without the headache. Most of them are built on SQLite. Explore Github for options that appeal to you. YapDatabase looks like the coolest one to me.

cocoa: what's the best way of designing a persistent cache?

I have to download some info from the Internet, like what's the phone number of a person. I want to save the info in disk in order to load it when my application starts. So I want to know whether Core data is the best choice? I mean is it fast enough? I want to load the info into NSCache object, is it a good class I can use?
It is a Plist type caching; key->value, only strings. Easy coding. For a few data I would recommend this. described here
The other one with NSArchiver->NSData: binary storage, any type of data, but you have to deserialize and deserialize. More coding, no limits ( well, you are doing the transformation) . I do proffer this one, because during the development, maybe I will need later some other data than text. Usually need to cache images. presented here actually the good answer is with downvote!
If you are storing anything that will be used between launches of the application then using Core Data is the way to go unless you have really, really basic requirements. NSCache is better as a temporary cache that is used by the application as it is running and for data that can be recalculated if it does not already exist.

Data Storage question

Another newbie question: What's the best way to store data in a Cocoa application written in Obj-C? For example if I want to create a sort of "quizzer" that quizzes the user with pre-written (and user-written) questions? How would I store these questions and answers? Core Data?
Thanks!
Of course it's Core Data!
It will handle everything.. take a look here: http://developer.apple.com/macosx/coredata.html
It's a full API that can handle:
ORM between databases and run-time objects
persistence
automatic building tools (like an ER-editor)
it's ready out of the box, you won't need to implement almost anything.. you will already have access to your data by just querying it to the object controllers
Probably this solution is over-sized for your problem but you will learn how to use it with a simple case, and I will come handy in the future..
Core Data is certainly an excellent option, as #Jack has shown. There are some other options as well.
NSCoding - You can make your model objects conform to the NSCoding protocol (similar to java.io.Serializable), which means you'd be able to directly write them to files. I've found that this is a great option when I don't have massive amounts of data to persist, and the data that I am persisting has a relatively simple structure.
SQLite - If your data is very relational, you may want to consider using a database (probably SQLite) directly. Core Data is an object store, and while it handles things like relationships between objects, it doesn't allow you to do really useful things like INNER/LEFT/OUTER/CROSS/NATURAL JOIN or other multi-table operators.
NSUserDefaults - if your data is very small and is just essentially key-value pairs, then you can probably throw it all into the NSUserDefaults object, which will persist it for you in the preferences file. However, even if your data is simple, NSUserDefaults might not be the best option if you have lots of it.

Resources