I have a singleton implemented in my app, but I've run into a problem when I switch between view controllers.
My app starts in one view controller, MainMenu, then switches to the Game view controller when the menu selection is made. I have a singleton class in the Game VC that is the object manager (called World) for the game. It loads content based on the menu selection in MainMenu. I can load up and quit back to the MainMenu VC fine. Singleton works fine. When I select from the MainMenu again (going from MainMenu VC to Game VC), my app crashes cause of an NSAssert to prevent the singleton World from allocating a second time, which is intentional.
How can I switch back to the Game VC without it trying to reinitialize my singleton?
Essentially, I want to skip the [[world alloc] init] line in my Game VC's init method. I can't figure out how to do this properly... it would need to be able to be handled the first time (when World doesn't exist) or any subsequent time (when World already exists as a singleton). I've tried if (!world) and that doesn't work.
This also begs the question... did I implement my singleton in the right place? Should I perhaps put it in the MainMenu instead? I just want to avoid it trying to reinitialize / reallocate the singleton when I switch between the two VCs.
If this helps, I'm exiting the Game VC by using [self.view removeFromSuperview]; Should I do it a different way?
If I understand the question correctly, you'd like to know how to create a Singleton class? A common way in recent times is to use grand-central-dispatch, as follows:
+ (MyViewController*)shared
{
static dispatch_once_t onceToken;
static MyViewController* instance;
dispatch_once(&onceToken, ^
{
instance = [[[self class] alloc] init];
});
return instance;
}
you can then access the instance with:
[MyViewController shared];
Before grand-central-dispatch, the technique was to put a static instance on the class and check if it's nil when calling the shared accessor. And the accessor would need to be wrapped with #synchronized(self) to ensure thread-safety. The GCD way has been shown to perform a little better.
Having said that, I recommend that you use singletons with volition. Do some research on why they're considered an anti-pattern, and investigate dependency injection as an alternative.
Dependency Injection vs Singletons
The problem with singletons is that they can lead to tight coupling. Let's say you're building an airline booking system. Your booking controller might use an:
id<FlightsClient>
A common way to obtain it within the controller would be as follows:
_flightsClient = [FlightsClient sharedInstance];
In order to test a class using the singleton, you now have to test the singleton at the same time, and this can get tricky, especially as your application gets more complex. Imagine testing Class A, depends on Class B, depends on Class C, depends on .... Not much fun!
An alternative is to use dependency injection, which simply means to pass the booking client to the booking controller using an initializer or property setter. You can do this manually or use a library for it. If you do it manually its still OK to declare the singleton, although arguably you will not need to as the top-level assembly class can retain the instance.
By using this alternative approach to singletons, classes will have loose coupling, and will be easy to test and maintain. (And with Dependency Injection, you'll have an equally fancy name ;) )
I wrote a dependency injection library, based on Spring: https://github.com/jasperblues/spring-objective-c
I was able to solve this by indeed moving the singleton initialization up into the MainMenu view controller as I was thinking. In my design, init for that VC is only called once upon app startup, whereas the custom init method in my Game VC gets called each time I switch to it.
Not sure if that's the optimal design I should be using, but it works for now.
Related
I have two or even more view controllers (A and B) which uses the same calculation method. I would guess the best way is to put the calculation method in its own class (lets call it C), define a protocol and thats it. If this is right, how do I know how to address the delegate?
If I alloc/init an object of the class C (the one with the calculatormethod) e.g. in class B I have the object pointer in class B - thats ok. But how do I get the object pointer known in class A or even other classes (i.e. how do I tell those controllers which want to use the delegate (i.e the same calculation method), how to address the delegate once it is alloc/init by class B?
Any help is very much appreciated!
I have two or even more view controllers (A and B) which uses the same calculation method.
Unless this is for calculating view layouts, it probably indicates you've have an MVC violation. View Controllers typically should not calculate anything. Their job is to manage user interaction. Data and calculations belong in the model.
If it is a proper view controller calculation (like managing layout), then you're correct that you want a delegate. "Delegation" is what Cocoa tends to call the Strategy pattern. You move your algorithm into another object and that lets you vary the algorithm without varying the rest of the code.
So in one case you need access to some model object, and in the other you need access to some delegate. In either case, the solutions can be similar. I'll call either situation "C" as you have.
One solution, particularly is you're using a storyboard, is to create "C" in the storyboard and wire it with an IBOutlet. You can create any object you like in a storyboard. Just drag out an "Object" and set its class to the appropriate class. Wire it up just like anything else. (This is a technique that is commonly used for multi-view nib files on OS X, and I had remembered translating over to Storyboards, but it doesn't work for sharing objects across scenes, only within scenes; so it's not as useful on iOS.)
Another solution, particularly for the model, is to implement it as a singleton, or to have a separate singleton (a "model controller") that returns it. You should not use the app delegate for this; use a singleton made expressly for this purpose.
You can create "C" in the application delegate and pass it into the root view controller (this is a proper use of the app delegate, because it's part of global program initialization). The view controllers can pass the object as part of their segues. This is my preferred solutions for passing model objects around.
If it really is a layout calculation delegate, this is probably part of some kind of configuration system (assuming it can change). The current configuration can be treated as a piece of the model, and all the above techniques still work.
If it really is just shared algorithms and doesn't vary, don't forget C functions. There is no rule that you must put all code into methods. Functions are ideal for stateless calculation. Categories can be used this way to, but simple functions have fewer complexities.
What you are saying is that both classes A and B have a common dependency (could be class C or simply a protocol C).
A and B don't need to know anything about how they are instantiated, they just need to know that they will be eventually provided with an instance implementing (protocol) C.
Another important thing is that you probably don't want C to be hold with a strong reference by either A or B.
I would look at which class F could have the responsibility to instantiate A and B.
The responsibility of this class (which could be described as a Factory) could also be to provide instances of A and B with a C instance.
So what I would do: Define a "factory" class that has methods to build instances of A and B.
Each of these methods would also provide with a C instance. This C instance could be a property of the factory class if you want it to be shared (or this factory class could also pick the C instances from a pool of available C instances).
UPDATE: not practical if you are using storyboards to instantiate your controllers. In this case you probably want to go with other given answer or implement your shared computational functions as methods of a singleton class C (see How to pass object between several views in storyboard, iOS Dev for example)
Use a superclass for A and B (and any number of additional controllers) that contains the calculation method. By using a superclass, you don't have to alloc init another class or use delegates, all the subclasses will have access to the method.
Another approach that would be more general would be to implement a category on UIViewController to add the calculation method. This way, any controller that descends from UIViewController (UITableViewController, UICollectionViewController, etc.) would have access to that method.
After Edit:
I see in your comments that your calculations have nothing to do with the controllers, just some sort of algorithm, so a category or subclass of UIViewController is probably not the best way to go. If you want to do it in another class, any controller that needs to use it, can instantiate an instance of that class, set itself as delegate, and get the result back through the delegate method (that is, if you even need a delegate -- if the calculation is fast, then you can just return a result from the method rather than using a delegate). After your controller gets the result back, the instance should be deallocated. You don't have to worry about which controller set the delegate, since each controller creates its own instance of the calculation class, and sets itself as delegate. I use this kind of structure for apps that need to do downloads from a server from multiple controllers. The download class is instantiated, does its work, sends back the result in a delegate method, and then gets deallocated. It only sticks around for as long as it needs to to do its work.
I've been thinking about using a singleton on my data class in my current app. I've also been thinking of reasons not to use the pattern and currently I am stuck in the middle.
The reason I am for the singleton in this case is due to accessibility to methods and properties easily that I need to use more than once throughout the app. I could use the appDelegate for this but that muddles up the area of concern as these methods / variables have nothing to do with the app state - more to do with user input. The data will be persisted with eventually with NSUserDefaults - which is a singleton already.
The reason I am against it is because its another singleton to an app that already bass one (The appDelegate)
My question:
Would using another Singleton to access the data model be the correct way / acceptable way of doing it - or should I look at another approach?
I personally think there would be nothing wrong with a singleton as a data model - using the app delegate to instantiate it when the app starts and then access its various methods / properties when I need them throughout the app. This would be the only other singleton in the app (Maybe another one for user management - e.g.; logging in / out / profile / credentials, etc? )
Any thoughts?
Thanks all!
There is no problem having multiple singleton classes within ios, in fact in many of my projects most of the classes are singletons. Normally I have the data access logic and control within a singleton and then actual object classes as instances.
As you have already identified you really do not want to be putting something into AppDelegate that does not apply to the whole app.
From my point of view do not instanciate the class from AppDelegate, simply have the class instanciate itself on first access.
Whenever I am explaining singleton Objective-C to people I always direct them to this site, it may be worth a view for you:
http://www.galloway.me.uk/tutorials/singleton-classes/
It explains only what you need in a really easy to understand way. The bit that does the 'self-instanciating' is this bit:
+ (id)sharedManager {
static MyManager *sharedMyManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedMyManager = [[self alloc] init];
});
return sharedMyManager;
}
You could use singleton in these case. Don't use delegate to hold values for your app. You may use same singleton for user management also.
Note : Don't use globals unless you need to do so. Singletons and top-level data should be used only when the data they contain truly belongs at the top level.
I have a theoretical-practical question. I can't understand how I must do. I have a class let's call them DataManager that manage all plist writing-reading things and I need to get access to plist (i.e. work with that DataManager class) from different UIViewControllers.
I also have one class, I call it ModelManager, that is work with all kind of "utilities classes", include my DataManager. ModelManager works only with one complex UIViewController right now, let's call it MainUIViewController for clearness. And for now, I thought that all calls from UIViewControllers will be comes to ModelManager and from it to end-call classes. But now I'm confused.
Here is an illustration of my architecture:
I'm see different approaches and don't know how to decide and if there is some rules or guides for that. So, here is my choices:
1) I add some interface to ModelManager and from my another UIViewController (not a MainUIViewController) allocate and initialise it.
2) I add some interface to ModelManager and create a property with reference to ModelManager in another UIViewController and when segues performs set this property from MainUIViewController.
3) Work with DataManager itself and allocate and initialise it from another UIViewController
4) Work with DataManager itself and create a property with reference to DataManager in another UIViewController and when segues performs set this property from MainUIViewController.
Which approach is correct?
I know that this is some kind of depends from developer which approach to choose, but I never read and didn't find any tutorial or guide of how to develop multi-class architecture.
Ask me about any circumstance that you want to know.
You can use a singleton or you can instantiate one instance of the class in your app delegate and pass it around to all your view controllers via #propertys on each controller. There's no right answer, it's mostly a matter of preference. I prefer to make my ModelManager/DataManager type classes singletons, but a lot of people are rabidly opposed to singletons. However, if you work with Cocoa for any length of time you'll find that it's full of them (NSUserDefaults, NSFileManager, UIDevice, probably some others I'm forgetting).
Here's a good example on how to create singletons: http://www.galloway.me.uk/tutorials/singleton-classes/
BTW: Once you have your singleton, learn how to use KVO to make your view controllers respond to changes in the model. It's pretty fantastic once you get the hang of it. http://nshipster.com/key-value-observing/
I've got a test project to use the private data object on several view controller.
(I've downloaded it from web & git-hub)
- (ExampleAppDataObject*) theAppDataObject;
{
id<AppDelegateProtocol> theDelegate = (id<AppDelegateProtocol>) [UIApplication sharedApplication].delegate;
ExampleAppDataObject* theDataObject;
theDataObject = (ExampleAppDataObject*) theDelegate.theAppDataObject;
return theDataObject;
}
First question is, theDelegate was casted with AppDelegateProtocol, even this applications UIApplication delegate name was ViewControllerDataSharingAppDelegate, and there's no warning. I can't under stand why, maybe it's because that was a id type?
(AppDelegateProtocol is a custom delegate protocol he declared in the AppDelegate.)
Second, it shows this kind of code on every view controller, and it seems like just a single-ton pattern.
I don't think this is not the best way to transfer data between view controller.
Which is the best way to transfer object data type?
Thanks.
Creating a protocol decouples the code somewhat from the specific implementation. You could conceivably have several applications, each of which uses its own custom class as an app delegate, but all implementations conform to the AppDelegateProtocol.
I used to use the app delegate to hold global data and methods a lot when I first started in iOS.
However, that fills your app delegate with app-specific code.
I've shifted away from that approach recently, and use a data container singleton (and perhaps a utility methods singleton as well.) As is typical for a singleton, I define a class method that lets me fetch the singleton. I add properties to my singleton as needed to store data, and then just use the class method to get a pointer to the singleton. I write my class method to lazy load the singleton.
Its also easy to make your data container singleton persistent by making it conform to NSCoding. Then every time you get moved to the background, just save your singleton somewhere. On app launch, read it in.
I'd like a critique of the following method I use to create objects:
In the interface file:
MyClass * _anObject;
...
#property (retain, nonatomic) MyClass * anObject;
In the implementation file:
#property anObject = _anObject
so far, so simple. Now let's override the default getter:
(MyClass *) anObject {
if(_anObject == nil) {
self.anObject = [[MyClass alloc] init];
[_anObject dowWhateverInitAction];
}
return _anObject;
}
EDIT:
My original question was about creating the object only (instead of the whole life-cycle), but I'm adding the following so that it doesn't through off anyone:
- (void) dealloc {
self.anObject = nil;
}
/EDIT
The main point of the exercise is that setter is used inside the getter. I've used it for all kind of objects (ViewController, myriad other types, etc.) The advantage I get is:
An object is created only when needed. It makes the app pretty fast
(for example, there are 6-7 views in an app, only one gets created in
the beginning).
I don't have to worry about creating an object before it's used... it happens automatically.
I don't have to worry about where the object will be needed the first time... I can just access the object as if it were already there and if it were not, it just gets created fresh.
Questions:
Does it happen to be an established pattern?
Do you see any drawbacks of doing this?
This pattern is quite commonly used as a lazy-loading technique, whereby the object is only created when first requested.
There could be a drawback to this approach if the object being created lazily takes a fair amount of computation to create, and is requested in a time-critical situation (in which case, it doesn't make sense to use this technique). However I would say that this is a reasonable enough thing to do should the object be quick to create.
The only thing wrong with your implementation (assuming you’re not using ARC yet) is that you’ve got a memory leak—using the setter means that your MyClass instance is getting over-retained. You should either release or autorelease _anObject after that initialization, or assign its value directly instead of calling the setter.
Aside from that, this is totally fine, and it’s a good pattern to follow when the MyClass is an object that isn’t necessarily needed right away and can be recreated easily: your response to memory warnings can include a self.anObject = nil to free up the instance’s memory.
It looks like a decent lazy initialization. Philosophically, one can argue that the drawback is that a getter has a side effect. But the side effect is not visible outside and it is kind of an established pattern.
Lazy instantiation is an established pattern, and it is used by Apple in their (terrible) Core Data templates.
The main drawback is that it is overly complex and often unnecessary. I've lost count of the number of times I've seen this where it would make more sense to simply instantiate the objects when the parent object is initialised.
If a simple solution is just as good, go with the simpler solution. Is there are particular reason why you can't instantiate these objects when the parent object is initialised? Perhaps the child objects take up a lot of memory and are only rarely accessed? Does it take a significant amount of time to create the object and you are initialising your parent object in a time-sensitive section of your application? Then feel free to use lazy instantiation. But for the most part, you should prefer the simpler approach.
It's also not thread-safe.
Regarding your advantages:
An object is created only when needed. It makes the app pretty fast (for example, there are 6-7 views in an app, only one gets created in the beginning).
Are you referring to views or view controllers? Your statement doesn't really make sense with views. I don't normally find myself needing to store view controllers in instance variables/properties at all, I instantiate them when I need to switch to them and push them onto the navigation stack, then pop them off when I'm done.
Have you tried your app without using this pattern? Conjecture about performance is often wrong.
I don't have to worry about creating an object before it's used... it happens automatically.
No, now you have to worry about writing a special getter instead. This is more complex and prone to mistakes than simple instantiation. It also makes your application logic and performance more difficult to understand and reason about.
I don't have to worry about where the object will be needed the first time... I can just access the object as if it were already there and if it were not, it just gets created fresh.
You don't have to worry about that when you instantiate it during your parent object's initialisation.
Yes this is an established pattern. I often use lazy instantiation like this as an alternative to cluttering up -init or -viewDidLoad with a bunch of setup code. I would assign the value to the instance variable instead of using the synthesized setter in the event that this object ends up being created as a result of something happening in -init.