Making a single copy of a singleton - ios

a design question:
I have a singleton (in objective-C but it doesn't really matter)
The singleton is a class (object) that is actually a data structure that many classes access, and is single (hence - a singleton)
Now I want to add the ability to undo - which is actually saving a snapshot of the state of the object - so I can go back to it.
What I actually need to do is to break the singleton-ness of the object (need one copy of it).
But this will not allow me to share it conveniently between all the classes.
Ideas?

"The singleton is a class (object) that is actually a data structure that many classes access, and is single"
I think it is easier to make your singleton object have a collection of the data structure. Then you just create copies of the data structure instead of copies of singleton.

The singleton pattern came in vogue about 10 years ago when design patterns were first being adopted by developers. In the years since then, the singleton has fallen into disuse because it is notoriously difficult to mock in unit tests. So the simplest answer is to abandon the singleton pattern completely in favor of a more friendly pattern.

You could implement a - (id) copy method in your singleton class.
In this method, allocate a new instance of your class, and set all it's properties to a copy of your shared instance's properties.

Related

Have multiple instances of a class point to one object #property

I will try to make this question as understandable as possible. I am implementing core data in my app, and I need to access the NSManagedObjectContext from around 10,000 different instances of a class (this class extends UIView). The Core Data stores what is displayed on these instances and the class builds it.
Everything that I have found so far uses View Controllers, of which you only have one instance, so you can just alloc init the VC in AppDelegate, set an #property for NSManagedObjectContext and be on your way. This does not work for my program.
What I want to do is have many instances of my CoreDataHelper class (which I will alloc init in the class that I have around 10,000 instances of, which all have a property pointing to the same NSManagedObjectContext. Is this a possible way to do it or will I have to make my program less flexible by moving all of the code to create the 10,000 different objects to the View Controller?
Sure, just put your NSManagedObjectContext in a singleton and all your instances can access the single class.
It does not matter if you get your managed object context from a singleton or from your app delegate (where presumably you the core data stack is set up by default).
To follow the pattern suggested by Apple with view controllers, do the exact same thing with your views: give them a #property of type NSManagedObjectContext and set it during initialization. Seems straight forward enough.
The advantage of the singleton is that you do not even need the property on your view but can call the singleton instead. But why go there? From your comments I understand that you do not really know how a singleton works. You don't need it. Go with the class property solution.
One more caveat: with your setup, you are seriously braking the MVC architecture by giving the views access to your data. Instead, you should indeed have a view controller do this and then populate your views with the retrieved data. I do not think that there is a compelling reason to deviate from this principle.

Core data design patterns

For my first IOS app I plan to incorporate CoreData however I'm a little unsure about the correct design pattern I should use.
In my app delegate I have the following 3 properties.
#property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;
#property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;
#property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;
I feel the best way to use these objects are to inject them into the constructor of all the relevant view controllers that need to access data from inside CoreData.
The cleanest way I can think of for that would be to create some kind of Repository class for each table I have in my data model which will house the above 3 objects and provide helper methods for accessing the tables data e.g. fetchAllTeams(). These repository classes can then be injected into the relevant view controllers instead of injecting all 3 objects above.
Does this sound like the correct thing to be doing in the world of CoreData & Objective-c?
Also whats the best way to create these repository classes, should I remove the default core data code and properties from the appDelegate (generated automatically) and place them inside an abstract repository class.
Should each instance of a repository have its own version of NSPersistentStoreCoordinator, NSManagedObjectModel and NSManagedObjectContext or should a single instance of these objects be shared among all repository instances passed in by the appDelegate.
Firstly, the base code that a Core-Data sets you up with can make the whole thing very confusing. The thing to understand is that Core-Data is a kind of wrapper around a variety of database technologies (sqlite, binary, xml) and by doing this, relieves you of the need to directly touch the database. The main class you are going to worry about in the beginning is NSManagedObjectContext. Think of it as a snapshot of the underling database which you can modify as you please and when you are done write that NSManagedObjectContext onto the database. The other classes you have there are really only needed for more fine-grained, low level control, and since this is your first app, best to leave those alone. You should read this, it is large, but you will gain a lot of understanding from it, especially how everything connects and their role.
To summarise though:
Really you only need to pass around the NSManagedObjectContext
You can do this my making an instance variable in every View Controller, OR,
You shouldn't go making more than one per app, unless you really need to, and then you need to make sure you merge them back together
You don't really need to create a repository of all the objects because NSManagedObjectContext does this for you...kinda... it will load objects into memory conditionally, there is a lot to this but the place to start is learning what a fault is (all in Apples documentation under NSManagedObjectContext or NSManagedObject)
think about what your objects represent and do. You can subclass NSManagedObject to represent your Core-Data object and place logic and validation inside of it - super handy.
Look into classes like NSFetchRequest and NSPredicate which are the two core classes for getting objects out of the NSManagedObjectContext.
Look into classes like NSFetchedResultsController which can tie very nicely into UI objects like UITableView.
Finally, Core-Data is a beast, and often you find yourself repeating common tasks all the time. You should look into this excellent framework which adds all sorts of helpers (like an easily accessible instance of NSManagedObjectContext, and one line object fetching, creating, deleting).
With regards this bit, my two cents...
Also whats the best way to create these repository classes, should I remove the default core data code and properties from the appDelegate (generated automatically) and place them inside an abstract repository class.
I'd definitely take out all the code that Xcode generates from the app delegate and put its in its own class. This might be a good read in explaining the basic core data stuff: http://commandshift.co.uk/blog/2013/09/07/the-core-data-stack/ (via #jrturton).
Should each instance of a repository have its own version of NSPersistentStoreCoordinator, NSManagedObjectModel and NSManagedObjectContext or should a single instance of these objects be shared among all repository instances passed in by the appDelegate.
You typically only have one persistent store coordinator (another good post here on that).
You add models to the coordinator, and also persistent stores. You can have multiple managed object contexts on a coordinator if you like.
A good example is a master detail style structure, you have a table view controller (backed by a fetch results controller), this uses the shared instance of the managed object context. When selected a managed object in the table, you pass this object into your detail view controller when creating it. You don't need to pass through, or use the shared context as that managed object will have its own managedObjectContext.
You can even create further child contexts from this if you like - think of this as a temporary context, you can change any objects registered in this context, and if you change your mind and don't want the changes any more you can just ignore and not save the child context.
Unless you have no way of accessing a managed object, or are at the top of the stack you can use the shared context. Keeping the use of shared context to only when its needed, I personally think keeps things simpler as you don't have to worry about what's (and where) using the global shared context through out your app. (Granted the shared context will be the base one anyway, but using a managed objects own context will mean when you save any changes to that context you know that that object will be effected).
Also to deal with simpler accessing and creating of managed objects I recommend mogenerator, there's a good post here about setting it up.

Confusion over running methods on Class Method instances of objects

So I'm getting myself into a confusion over where my data's going and where it's stored in my application. It's not a specific question so hopefully someone can provide a generalised answer.
I need to pass some data around between a few UIViewController instances, and I'm currently doing that with a singleton object called my dataManager. This class has one method, a class method, called + (LCDataManager *) sharedDataManager, and that method basically checks if whether the sharedDataManager already exists, if so, return it, if not, create it and set up its variables. This means that I can refer to that class anywhere I like, access and modify its variables anywhere I like, from across multiple classes.
First question: is this the correct / best / most appropriate means of passing data around like this? I'm hoping it obeys MVC, it feels like it does, and I hope I'm right.
Second question: what if I want to put an instance method in that class, and call it from within the class method? Let's say my sharedDataManager needs to call a method to grab some objects one of its variables (an array), and put them in another array, then send that back out again. I can't do that, can I? What's the way around that? If I make an instance of that class (rather than using the shared instance), I lose the ability to use that instance across multiple viewControllers.
I'm hideously confused, and it seems like it's not the problem I'm making it. Appreciate any guidance, and preferably not that "Read the Apple documentation" stuff – they write as if you already know what you're doing, and frankly I don't yet.
First question: is this the correct / best / most appropriate means of passing data around like this? I'm hoping it obeys MVC, it feels like it does, and I hope I'm right.
Your design is perfectly MVC compliant.
Second question: what if I want to put an instance method in that class, and call it from within the class method?
you can surely define an instance method and call it like this:
[[MyModelClass sharedModel] myInstanceMethod];
indeed, [MyModelClass sharedModel] will give you an instance of MyModelClass (which should be guaranted to be unique being it a singleton).
If you want to call the instance method from the sharedModel class method, you could also do that, because sharedModel owns a reference to your singleton, so it can send messages to it.
is this the correct / best / most appropriate means of passing data around like this?
There's nothing wrong with only having a single instance of LCDataManager, but using the Singleton pattern has potential problems. An alternative is to just initialize one LCDataManger and to pass it around to wherever it's needed.
what if I want to put an instance method in that class, and call it from within the class method?
The accessor + (LCDataManager *) sharedDataManager should only return the instance. I guess what you want is something like
+ (LCDataManager *)preparedDataManager {
LCDataManager *shared = [self sharedDataManager];
[shared doSomeInstanceMagic];
return shared;
}
- (void)doSomeInstanceMagic {
// magic!
// grab some objects one of its variables (an array),
// and put them in another array
}
Matthijs Hollemans has an excellent three-part tutorial on his blog about the correct way to make your view controllers talk to each other:
Part 1
Part 2
Part 3
there is no problem with this development architecture, and it is the must used (I think) in the iOS development. In the book IOS Programming: The Big Nerd Ranch Guide they call it Model View Controller Store.
Regarding your second question, yes, you can declare instance methods and call then from your sharedDataManager. What is not usual is creating other instances of a singleton class, but it is possible.

How to ensure destruction of singleton in IOS 5 with ARC?

Say, I want to create a singleton which has some data inside. The data is dynamically allocated only once, as it expected on singleton.
But I would like to now under when and how this data can be is released. Should I establish special method which will destroy the singleton? To be more specific - when the method 'dealloc' for this singleton will be executed? who is responsible for that?
You can declare a method/function you call explicitly.
The simplest way is to have a static C++ class hold it, then release it in its destructor. If you have multiple singletons, then this approach does not extend very well because the destruction order is implementation defined.
Another alternative (and better design) would be to avoid the singleton approach, and just use it as a regular instance in another class which lives for the duration of your app (an app delegate is a commonly known example).
As to 'when', it depends on its dependencies and how it's used. It's also good to try to minimize external influence in destruction.
In general, a singleton is not different to a normal object. It is freed, if there is no (strong) reference to it anymore. Usually, you control that there is one object only by a static variable. This variable is created at compile time; therefore it can not be freed. But all the 'real' object stuff can.

Recipes to pass NSManagedObjects amongs UIViewControllers

Within an application it's possible to have different UIViewControllers that need to share the same NSManagedObject. I'm usually do the following:
#interface CustomController : UIViewController
#property (nonatomic, retain) ProductNSManagedObject* productManaged;
#end
Then when I istantiate CustomController I inject it like the following:
customController.productManaged = ....
once done, CustomController is responsible to release it.
This approach works well (I don't know if is it correct), but what to do when a controller need that object but it's not a direct child of the controller that has that object? e.g.
MainController -> ChildController -> SubChildController -> ....
where MainController has the managed object.
Do I have to create a lot of intermediary properties or do I need to execute a fresh NSFetchRequest or something else?
The same aspect could be applied to the NSManagedObjectContext. Searching around I've found that the context can be grabbed from the application delegate that posseses it (if any). But this approach lacks of flexibility as Marcus Zarra wrote in passing-around-a-nsmanagedobjectcontext-on-the-iphone.
Any suggestions? Thank you in advance.
I create a singleton object that contains the managed object context that will be used throughout the application. I put any supporting code related to the data (e.g., persistent store coordinator) inside this singleton and keep all of the view and controller information separated from it.
In one case, I need a managed object context for another thread. It became apparent that it would be useful to refactor and put that context inside the same singleton. Then merging between the two contexts can be done inside the singleton.
This has helped me manage my code. You might consider it.
This is a very common question (see here and here for related ones). As I wrote in the answers for the related questions, you should stay away from singletons and create a separate object that will take care of object instantiation, of creating the object graph for your application. This separate object can hold references to all shared objects and supply them to the objects being built, so that none of your regular objects has to keep a reference to something just to pass it as a dependency to other objects. See this blog post for more rationale against singleton misuse and for further pointers, especially the articles by Miško Hevery.
I have created a sample Xcode project that shows how to wire an app without singletons, keeping the coupling low and resolving other singleton issues. It’s very simple at the moment, I will add more common use cases later.

Resources