How can I hold common runtime data in cocoa app? - macos

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.

Related

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.

Cocoa MVC ≠ actual MVC?

Today I was getting some refresh about software design patterns.
In particular I was wondering about the difference between MVC and Three-tier-layer. Basically, from what I read on wikipedia and other sources, the main difference between the two is the components interaction:
A fundamental rule in a three tier architecture is the client tier
never communicates directly with the data tier;
whilst
...the MVC architecture is triangular: the view sends updates to
the controller, the controller updates the model, and the view gets
updated directly from the model
Now: if we take the apple docs regarding this matter we see this:
And they clearify that Views and Model shouldn't communicate directly:
view objects are typically decoupled from model objects in an MVC
application
and
When a model object changes (for example, new data is received over a
network connection), it notifies a controller object, which updates
the appropriate view objects
And so on.
So, what's the matter here? Is Cocoa adopting its own idea of an MVC, regardless of the common one? Or am I missing something in the common way of seeing an MVC architecture?
While it can be said that Cocoa's version of MVC is a sort of subset of the actual definition of MVC, they are not separate entities. The Cocoa version of MVC typically revolves around the use of a View (typically an NSWindow and/or an NSView), a controller (typically an NSWindowController), and a model layer (anything from a simple array to a Core Data stack). The separation of powers in this model is clear, but where in the 'tier' structure that Wiki defines should each of these belong?
I would argue that the Controller and the View are a part of the client layer. Not only is the controller responsible for the delegation between the model and the view, but it is responsible for responding to user events and determining the correct course of action to take during non-framework error handling. By taking this approach to MVC, you can now begin to see how Cocoa does, in fact, satisfy the broader definition of the pattern.
A fundamental rule in a three tier architecture is the client tier never communicates directly with the data tier;
This one's probably the hardest to reason about of the 3, and it involves delving into what "communication" actually means in the context of the pattern. When we say communication, what we mean is that the controller has no direct involvement in the actions taken by the model. That's not to say that the controller cannot order a change in the contents of the model, but rather that the controller does not have a hand in how the model updates itself. The controller acts as a director, not an implementer, which vastly simplifies the creation of a database layer, and is one of the reasons that Core Data and SQLite3 exist as external frameworks rather than as Foundation classes.
view objects are typically decoupled from model objects in an MVC application
That brings up one of the age-old taboos when programming with the pattern: making your views too smart. The controller provides a solid barrier between the model and view, such that the controller acts as a director and a filter for content from the model layer. Without any such barrer, say a tableview, would have to ensure that every cell had a copy of the data from the database, and that each cell knew when and how to update itself when a change is propagated in another cell. In Cocoa, this is where our NSWindowControllers come in. They manage the display of a root view and act as a barrier between some model and the content of the view it manages. Though, it is important to note that the controller objects in Cocoa are view-biased, mostly because it would be nearly impossible to provide a generic outlet to any kind of model layer without quite a bit of unnecessary glue.
When a model object changes (for example, new data is received over a network connection), it notifies a controller object, which updates the appropriate view objects.
That's the way it should be, for the reasons I've laid out above. But, to build on the networking example you've given, consider this:
Given an NSOperation that fetches data, and a controller that manages a tableview, you would probably not like the controller sticking its fat fingers into the operation, nor would you like the tableview to receive raw NSData and have to spend valuable rendering time processing the result and displaying it.
And so on. So, what's the matter here? Is Cocoa adopting its own idea of an MVC, regardless of the common one? Or am I missing something in the common way of seeing an MVC architecture?
I guess the conclusion I would draw from this is that your definition of the separation of powers in MVC and in how Cocoa does it is off. Cocoa is fairly rigid about adhering to the pattern, though there is an interesting contemporary movement within the Objective-C community towards MVVM.
You are correct the MVC practiced in most cocoa apps is not the MVC as it is defined in the text books. There are many variations of MVC employed by different frameworks. The MVC employed by tools with visual designers are heavily influenced by their visual designer implementation. With XCode you have story boards and nibs. The cocoa libraries and the way concerns are separated are influenced by this. If you want to take advantage of these tools, I would recommend understanding how concerns are separated by Xcode and work within this approach. Your code will coexist with it more smoothly. Apple documentation will help with this.
That being said, MVC is about separation of concerns. Separating concerns is hugely important in designing and maintaining software. Separating concerns properly can reduce dependency, reduce cyclomatic complexity, and make your code much more testable and maintainable. I think it is good that you are paying attention to this and whatever way you structure MVC should look to the reason why you are separating concerns as the guide to implementation.

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

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

Is there a Notification when CoreData finished reading data from disk?

I have a Mac (not document) app, that uses CoreData.
When launching the app, it reads the data stored on the filesystem.
I have to setup some things in -(void)applicationDidFinishLaunching based on the information stored using CoreData.
So it would be nice to know when my app read everything from disk.
If I do my setup in -(void)applicationDidFinishLaunching i doesn't work. If I do it a few seconds later it works!
Thx!
If you are using object controllers that automatically prepare their own content, you can observe arrangedObjects to find out when they have fetched their content. This does not guarantee that the actual objects are not faults. In fact, that's one of the main strengths of Core Data: objects are lazily loaded from disk.
If you for some reason want to make sure that most disk activity has taken place in applicationDidFinishLaunching, you can perform a custom fetch that specifically does not return objects as faults. Look up "prefetching" in the Core Data documentation. However, there is no guarantee that Core Data won't fault these objects at a later time due to memory constraints, thereby incurring another disk read when those objects are loaded again.
You can of course also use the NSBinaryStoreType, in which case the entire store is loaded into memory synchronously when it is added to the persistent store coordinator.

iTunes XML Parsing in cocoa

I am developing an application in cocoa .I need to parse a iTunes XML file of large size(about 25Mb).I am using the following code snippet now
NSDictionary *itunesDatabase = [NSDictionary dictionaryWithContentsOfFile:itunesPath];
But this is a little bit slow
Is there any faster method to load the entire data to a dictionary??
The reason you're having such slow performance is because NSDictionary reads everything into memory all at once. For a large iTunes library, this can take a long time and -- feel free to confirm this with Activity Monitor -- a metric assload of memory. (This is the precise technical term for that amount of memory)
The alternative in these situations is to use a callback-based XML parser (generally known as "SAX" parsers). These parse XML documents an entity at a time and call your callback methods. In Cocoa, the NSXMLParser class provides this functionality. You set your class as its delegate, call the parse method, and the parser starts calls the delegate methods as it reads tags, attributes, text, etc. in the XML file.
Now, this is obviously harder than just loading everything into an NSDictionary and walking the resulting tree of objects. You'll need to keep track of state information yourself. And you'll have to "build up" your objects progressively, so organizing your classes can be difficult.
However, you can ignore the XML you aren't interested in, and that saves a lot of memory. And, depending on what data you're getting out of iTunes, you may also be able to end the parsing as soon as you've gotten the data you need. Even if this does end up taking quite a while, at least you'll be able to show your user a progress bar or some other indication that your program is working, which is much better than just hanging for 10-20 seconds while NSDictionary loads a giant XML file.
If you're able to use third-party frameworks, run, do not walk to EyeTunes. (BSD license.) It's an abstraction layer around Apple Events for communicating with iTunes, and as such it doesn't parse the XML database directly (I think, it's been a while since I've used it), but you'll have get/set access to anything in the XML.
Try to use libxml:
http://www.cimgf.com/2008/08/18/cocoa-tutorial-libxml-and-xmlreader/
To minimize highest memory footprint, create and drain NSAutoreleasePool in your loop

Resources