I'm creating a wrapper class for an existing singleton class. Since I'll be accessing the singleton several times, I'd like to store it as an ivar in my wrapper class...
#interface WrapperClass ()
#property (nonatomic, strong) SingletonClass singletonObj;
#end
...so that I don't have to constantly write [[SingletonClass sharedInstance] methodName]. Instead I can write [singletonObj methodName]. It just feels cleaner to me.
I'm new to iOS development, so I'm wondering if there's anything fundamentally wrong with this approach.
Also, with ARC, should I be storing the singleton with a strong reference?
Unless your doing something crazy the likelihood is the extra retain/release should cause no issue.
Therefore there is no real issue with storing it in an ivar...
A better reason for doing this would not be to save your typing but to improve the testability /reusability of the class. By making it an ivar it allows you to inject a different class in to change the behaviour.
I would consider making an accessor that will by default give me the singleton but still allow me to inject a different class if I choose like this
- (SingletonClass *)singletonObj;
{
return _singletonObj = _singletonObj ?: [SingletonClass sharedInstance];
}
Update:
It's also worth thinking about "why would you make using this singleton different from using an ivar?". If you use it throughout your class like it was an ivar then why do you access it in a completely different way?
For example often when I use a managedObjectContext there is only one in my whole app. A lot of people use the app delegate as a singleton and access it that way but I prefer to pass it along as an ivar. Conceptually the managedObjectContext is just another object that I am using like any other ivar so why should I have to mentally switch how I access it?
This is bad
[(MyAppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
Good
self.managedObjectContext;
This now gives me two advantages.
If my class is littered with calls to [(MyAppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext]; then it is hard to rip it out of this project and place it in another without a risky search and replace. If I access the singleton in one place the "accessor" then I only have one place to change the code.
In my production app I probably want my data to be persistant so I would give the object access to a managedObjectContext with a persistant store, whereas in my tests I don't want state to be persisted between tests so I would give the object a non persistant store instead.
It makes sense.
Just initialize your singleton and store it in the ivar.
That said, your code is actually defining a property, which is not the same thing of an ivar.
For instance you could define your singleton i var like follows
#implementation WrapperClass {
SingletonClass * _singleton;
}
and then initialize the singleton in the default constructor
- (id)init {
self = [super init];
if (self) {
//...
_singleton = [SingletonClass sharedInstance];
//...
}
return self;
}
You can just define a macros, like this:
#define _SINGLETON(method) { [[SingletonClass sharedManager] method]; }
Then you can use it in your code like this:
_SINGLETON(methodName);
You can define this macros in the SingletonClass.h, and then you will have possibility to use it anywhere, there your header is imported.
This way you don't need to think about iVars.
Related
I have doubts regarding the creation of singleton class in Objective-C/iOS.
Where ever I see the trick to create a singleton class in objective-C is this code
+ (id)sharedManager {
static MyManager *sharedMyManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedMyManager = [[self alloc] init];
});
return sharedMyManager;
}
Whenever I call [MyManager sharedManager] of course I get the same address. However, I can also write [MyManager new] in which case the address is different.
1.Isn't the concept of singleton class is that it restricts the instantiation of a class to one object?
2.If we can create another object its not a singleton anymore, is it?
In my iOS app I tried [UIApplication new]. I got an exception in runtime. Now this I get. You cannot make another instance of UIApplication since its a singleton class.
So why the use of shared instance considered to be the way of creating a singleton class or have I got this all wrong?
The sharedManager is the convenience method you'd use to access the singleton instance. While this doesn't guarantee that there will be only one instance of that manager over the app, if everyone is using sharedManager then there will practically exist only one instance of that manager.
This kind of singletons are singletons by convenience, not by implementation. You should use them, for multiple reasons:
you can unit test them, by calling alloc init in your unit tests and making use of that brand new allocated object
it makes your life easier if decide to later refactor the manager and no longer use it as a singleton if you consider it from the begging like a regular object to work with
Of-course, you can make a singleton by-the-book by overriding the init and allocWithZone: to either return the only instance or by raising an exception, however I'm not sure they'd worth the effort.
There's a very good tech talk regarding singletons held by Misko Hevery in the Google clean code talks playlist, the link to the video: here. This kind of singletons are referred as lower case S singletons, not capital S ones in the video, and Misko explains very well why they are preferred.
It doesn't break singleton concept. You choose your way to implement what you want. If you want to create only singleton instance, you can make run error by override init function:
[NSException exceptionWithName:NSInternalInconsistencyException
reason:#"bla bla bla..." userInfo:nil];
or
you can override it to force return to shared instance.
Of course, you can. But it not recommend if you are using singleton.
Objective-C uses a pragmatic approach. Your +sharedManager method returns a singleton. If someone is stupid enough to call [SingletonClass new] or [[SingletonClass alloc] init], that's their problem. They'll get what they deserve. There is no reason to prevent people from shooting themselves in the foot if that is what they want to do.
There are millions of programming errors that people can make and that the developer of a class or the compiler cannot prevent. No point wasting effort on preventing this particular error.
I have a single ton which is working fine, but i don't want to use singleton instead any alternative best way
find my code for reference
Myclass.h
+ (instancetype)shareInformation;
Myclass.m
+ (instancetype)shareInformation
{
static Myclass *manager;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
manager = [[Myclass alloc] init];
});
return manager;
}
MyNextClass.m
[[Myclass shareInformation] methodofMyclass:^(NSDictionary *results, NSError *error) {
//my code
}];
i have a class Myclass in which i am using a singleton to init manager = [[Myclass alloc] init]; and i am calling this in other class MyNextClass but i don't want to do this in this way i mean i don't want to use singleton pattern i need some this alternative for what i do here
I'm guessing you want to avoid using the singleton as it's considered an anti-pattern.
A solution would be to use a dependency injection container to wire up your application and configure it to resolve your object as a single instance.
I'm not familiar with ios development but Typhoon looks like popular choice.
You can use a singleton or you can use a normal instance, it's up to you. One of the major benefits of a singleton is so that you can get a reference to it anywhere without difficulty.
You could always create a class, and pass a reference of it anywhere you want to use it. For example in your view controller you create it, make sure you create a property of it in your following view controllers and then pass that same reference to the new view controller.
It's best to use a singleton if that's what you're trying to accomplish and you only need one instance though.
Another option, for "global" data, is to make use of the AppDelegate. You can place simple properties in the AppDelegate itself, or define a property (or explicit "getter" method) which returns a pointer to some more complex "global" object.
Note that using the AppDelegate this way is considered "bad form" by many, but there's really not that much bad about it, other than accessing the AppDelegate itself is a bit awkward. (And it upsets the sensibilities of those who are sure they know what "separation of concerns" really means.)
This question already has answers here:
Singleton Instance vs Class Methods
(2 answers)
Closed 9 years ago.
So, pretty simple question. Ignoring the implications of over-use of the singleton pattern. I'm trying to find a reliable singleton patter in Objective-C. I have come across this:
#implementation SomeSingleTonClass
static SomeSingleTonClass* singleInstance;
+ (SomeSingleTonClass*)getInstance
{
static dispatch_once_t dispatchOnceToken;
dispatch_once(&dispatchOnceToken, ^{
singleInstance = [[SomeSingleTonClass alloc] init];
});
return singleInstance;
}
- (void)someMethodOnTheInstance
{
NSLog(#"DO SOMET WORK")
}
#end
This I am fairly happy with but it leads to a lot of this:
[[SomeSingleTonClass getInstance] someMethodOnTheInstance];
My question is, why is this better than a purely static class.
#implementation SomeStaticClass
static NSString* someStaticStateVariable;
- (id)init
{
//Don't allow init to initialize any memory state
//Perhaps throw an exception to let some other programmer know
//not to do this
return nil;
}
+ (void)someStaticMethod
{
NSLog(#"Do Some Work");
}
All you really gain, is mildly cleaner looking method calls. Basically you swap out this:
[[SomeSingleTonClass getInstance] someMethodOnTheInstance];
For this
[SomeStaticClass someStaticMethod];
This is a minor simplification for sure, and you can always store the instance within your class. This is more intellectual curiosity, what Objective-C god am I pissing off by using static classes instead of singletons? I'm sure I can't be the first person to think this, but I promise, I did a duplicate search first. The few answers I found, I felt like were based on older versions of cocoa, because even the discussed singleton patterns seemed to suffer from threading issues.
Static class : Used when you want to group together utility methods that are state independent.
Singleton : Used when you have multiple methods that share a state.
I've found it convenient to do a mix of both. I use a standard singleton pattern similar to your first that results in:
[[MyClass defaultInstance] doSomething];
But I also want to be able to create other instances of the same class:
MyClass *secondInstance = [[MyClass alloc] init];
[secondInstance doSomething];
When I want more concise access to call methods on the singleton instance, I define class methods as follows:
// class method to call a method on the singleton instance
+ (void)doSomething
{
[[MyClass defaultInstance] doSomething];
}
So with that, I can use:
[MyClass doSomething];
You're pissing off no Objective-C gods with a class like that. Actually, Apple recommends to use that pattern in some cases (I think they mentioned this in one of the ARC session videos, where they discussed common design patterns and how to implement them using ARC).
In other cases, where you can have multiple instances of a class, but want a default one, you'll of course have to use the shared instance approach.
The first example seems to be needlessly creating a singleton-like instance of a class. I say needlessly because from your other comments it appears that the class doesn't declare any properties or instance variables. Given that the fundamental purpose of an object is to provide storage for state, an object with no instance variables is rarely a useful thing.
Your second example shows a class that would never be instantiated. Again, the fundamental purpose of a class in Objective-C is to act as a factory for instances, so a class that's never instantiated isn't really useful or necessary.
Instead, you can just provide a set of C functions. C functions don't need to be associated with a class at all. So consider doing something like this:
static NSString* someStaticStateVariable;
void someFunction(void)
{
NSLog(#"Do Some Work");
}
The functions can be in separate .h/.m pair, or can be incorporated in the .h/.m for an existing class if it makes sense to do so (generally, if the functions are closely associated with the concerns of that class).
I've been reading a lot of threads and blog articles about how to implement a singleton in objective-c, several of them maybe being a bit deprecated (year 2010 or earlier), and it seems like people have different opinions regarding this issue... Does Apple have documentation about implementing a singleton? I couldn't find it. If so, could somebody tell me where?
I need a singleton for a class that has some both public and private variables. Currently, this is the implementation I have for such class:
#interface MySingleton ()
#property (strong, nonatomic) NSString *state;
#end
#implementation MySingleton
#synthesize state = _state;
#synthesize count = _count;
static MySingleton *sharedObject = nil;
+ (MySingleton *)sharedInstance
{
static dispatch_once_t _singletonPredicate;
dispatch_once(&_singletonPredicate, ^{
sharedObject = [[super allocWithZone:nil] init];
});
return sharedObject;
}
+ (id)allocWithZone:(NSZone *)zone
{
return [self sharedInstance];
}
Should be this the recommended way? And how should I initialize the instance variables, public and private?
Another issue I'd like to make clear about singleton is: will this generate a memory leak? Is the use of singletons actually recommended in iOS?
Thanks
The above is correct, along with #miho's comment about includng the static object inside of the sharedInstance method. But there is no reason to override +allocWithZone:. Singletons in ObjC are generally "shared," not forced. You're free to create other instances of a "singleton." If it's illegal to create other instances, then you should make init perform an NSAssert rather than fooling the caller in +allocWithZone:. If your singleton is mutable (and most are), you absolutely should not override +allocWithZone: this way.
Another issue I'd like to make clear about singleton is: will this generate a memory leak?
No. This object will never be released, but it will always be accessible. That is not a leak.
Is the use of singletons actually recommended in iOS?
Yes, and it is a very common pattern, used all over the Cocoa frameworks. That said, there are various other patterns that have started to recently become somewhat popular among developers. Dependency Injection is getting some interest, though I don't see it in practice very often. Reducing your reliance on singletons can improve testability, and I have been experimenting recently with how to eliminate some of them in my code with some success. But they have a long, proud history in Cocoa, and I do not consider them a problem.
EDIT: you have one actual bug in your code. You should be calling [[self alloc] init], not [[super alloc] init]. There's no reason to ever call +allocWithZone:, just use +alloc. (The time when ...WithZone: methods were useful has long passed.)
In Xcode, under 'Search Documentation' enter Creating a Singleton Instance. There are lots of results (but the link above, at the bottom of the page, has example code).
Yes, this is the recommended way. There is only one small difference of how I use it: I define the sharedObject as static variable inside the + (MySingleton *)sharedInstance method, because it shouldn't be possible to access the variable from anywhere else then from the getter method.
And no, you won't create a memory leak. When your app is terminated all reserved memory used by your app will be released anyway and there is no other situation where a static shared instance should get released. In pre-ARC area it even was common to override the release method do prevent accidentally releasing of the object.
A bit of warning using gcd for singletons:
dispatch_once(&_singletonPredicate, ^{
sharedObject = [[super allocWithZone:nil] init];
});
if the init method for some reason addresses the singleton object directly or indirectly, there will be a deadlock. For this reason I believe that the more appropriate way to write a singleton is through the
+ (void) initialize
method
I am still using the singleton header thingy from CocoaWithLove - may be a bit dated but still works like a charm. It basically does the same as described here referring to Apples documentation and I would assume at least Apple's documentation (bottom of this page) is still valid. There are people assuming it will stay valid indefinitely sine it is the official solution Apple suggested.
Often times I initialize my model class variables in my AppDelegate so they can be used by different ViewControllers without passing their instance across class files. However, every time I import AppDelegate into a .m file to access these variable's data I feel like I'm doing some wrong.
Is this the the correct way for accessing these variables or should I be doing something differently?
EDIT:
My problem isn't how to access the variables. I currently use this line of code to get my appDelegate instance:
id appDelegate = [[UIApplication sharedApplication] delegate];
Conceptually, I want to know if this is the accepted way to interact with an application's model classes. It seems, to me, that an application's AppDelegate manages the application overall. So it seems counterintuitive to import this class into other classes further down an application's class chain.
Is this the the correct way for accessing these variables or should I
be doing something differently?
You'll find that different people have different opinions about this. The style that I prefer is to have the app delegate pass the necessary information to the first view controller, and have that view controller pass it on to whatever view controllers it creates, and so on. The main reason for this is that it prevents child view controllers from depending on things that they have no business knowing about.
If you have some detail editor, for example, you want to be able to pass that editor exactly what it needs to do its work. If you give it that information, the editor is completely flexible -- it'll edit any information that you give it. If the editor knows that it should get its data from some external object, like the app delegate, then it loses some degree of flexibility -- it can only get data from the thing that it knows about.
So, it's fine to set up your data model in the app delegate. But when it comes to providing access to the model, think: tell, don't ask. That is, have the app delegate tell the first view controller what model object to use, and have that controller tell the next one, and so on. If you have to ask, you have to know who to ask, and that's where the dependencies start heading in the wrong direction.
every time I import AppDelegate into a .m file to access these
variable's data I feel like I'm doing some wrong.
Trust that instinct. Think about why it feels wrong.
I agree that sometimes it seems like the AppDelegate is the logical place to put things that you only want implemented once but may need from several places. Creating a singleton for each one is fine, if those things are complicated, but it does create a lot of additional files and confusion to the project. I also agree with the majority of answers here, that building dependencies on the AppDelegate is a really poor design.
I think the best solution is to create a Protocol! Then put an IBOutlet to a property to do what you need to have done in each of the controllers that need the function. Protocols are the standard objective-C way to uncouple classes.
So, as an example, maybe I have a database URL that I may need from a bunch of places. Probably the best way would be to set a property with it each step along the way. But in some situations that may be cumbersome because of using a stock controller and not wanting to subclass it. Here is my solution:
Create file: MainDatabasePovider.h
#import <Foundation/Foundation.h>
#protocol MainDatabaseProvider <NSObject>
#required
#property (nonatomic, readonly) NSURL *applicationDocumentsDirectory;
#property (nonatomic, weak) NSURL *mainDatabase;
#end
Now "anyone" (i.e., any class) that says it implements the MainDatabaseProvder protocol is guaranteed to provide the two methods above. This could be the AppDelegate or ANY object.
Now if I want my AppDelegate to provide the information I change the AppDelegate.h file to have:
#import "MainDatabaseProvider.h"
#interface AppDelegate : UIResponder <UIApplicationDelegate, MainDatabaseProvider>
#property (strong, nonatomic) UIWindow *window;
#end
(The only change is to add the MainDatabaseProvider protocol to the #inteface line, again this could be done to ANY class that you want to provide the function).
In my AppDelegate.m file I have to write the two methods...
#implementation AppDelegate
...
#synthesize mainDatabase = _mainDatabase;
...
- (NSURL *) applicationDocumentsDirectory {
return [[[NSFileManager defaultManager] URLsForDirectory: NSDocumentDirectory inDomains: NSUserDomainMask] lastObject];
}
- (void) setMainDatabase: (NSURL *) mainDatabase {
if( _mainDatabase != mainDatabase ) {
_mainDatabase = mainDatabase;
}
}
- (NSURL *) mainDatabase {
if( !_mainDatabase ) {
NSURL *docURL = self.applicationDocumentsDirectory;
self.mainDatabase = [docURL URLByAppendingPathComponent: #"My Great Database"];
}
return _mainDatabase;
}
...
#end
Now in my controllers or other classes that have need of getting the MainDatabase I add the following:
In their .h files:
#import "MainDatabaseProvider.h"
...
#interface myGreatViewController: UIViewController
#property (nonatomic, weak) IBOutlet id <MainDatabaseProvider> mainDatabaseProvider;
...
#end
This property can be set in what was formerly known as InterfaceBuilder by control-dragging or can be set in code in prepareForSegue or I like to provide a custom getter that default it to the AppDelegate in case I am lazy or forgetful and don't do either of the above. In their .m file is would look like:
#implementation myGreatViewController
#synthesize mainDatabaseProvider = _mainDatabaseProvider;
...
- (id <MainDatabaseProvider>) mainDatabaseProvider {
id appDelegate = [[UIApplication sharedApplication] delegate];
if( !_mainDatabaseProvider && [appDelegate conformsToProtocol: #protocol(MainDatabaseProvider)] )
return appDelegate;
return _mainDatabaseProvider;
}
// To get the database URL you would just do something like...
- (void) viewWillAppear: (BOOL) animated {
NSLog( #"In %s the mainDatabaseProvider says the main database is \"%#\"", __func__, self.mainDatabaseProvider.mainDatabase.path );
}
Now the mainDatabaseProvider can be ANY object. I have the ability to set it in InterfaceBuilder or my StoryBoard (although I don't really think of this is a user-interface item so I typically wouldn't but it is pretty typical to do it that way), I can set it in code outside my controller before it gets loaded in prepareForSegue:sender: or tableView:didSelectRowAtIndexPath:. And if I don't set it at all it will default to the AppDelegate if I have configured it properly.
I can even put some safe guards in for when I forget to do things in my old age by changing the getter listed above to help me out with something like:
- (id <MainDatabaseProvider>) mainDatabaseProvider {
if( !_mainDatabaseProvider ) {
id appDelegate = [[UIApplication sharedApplication] delegate];
if( ![appDelegate conformsToProtocol: #protocol(MainDatabaseProvider)] ) {
NSLog( #"Hey!! The mainDatabaseProvider is not set and the AppDelegate does not conform to the MainDatabaseProvider protocol. How do you expect me to figure out where the database is!" );
} else {
return appDelegate;
}
return _mainDatabaseProvider;
}
You should seriously avoid importing the AppDelegate everywhere and you should feel like you are doing something wrong each time you do it (+1 for that). You are essentially creating a Big Ball of Mud and should reconsider your design. If for example you are using CoreData for your models consider a framework such as Magical Panda Active Record to retrieve data. I work on an enterprise application and the AppDelegate.h is only include in AppDelegate.m.
I'm importing them too and use it like this:
AppDelegate *delegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
[delegate variable];
Another way can be to use a Singleton.
Put this method in your AppDelegate class
+ (AppDelegate *)get {
return (AppDelegate *) [[UIApplication sharedApplication] delegate];
}
And when you need to call your AppDelegate use:
[AppDelegate get];
That is one way of doing it, yes, however it is not very elegant. Singletons are a way too, yes, however not very elegant :) - and reeealy NOT easy to test your code, if you have to mock out all your singletons.
Instead what I probably would do is to have one singleton for a service provider, and ask this service provider for an instance your model provider.
Say, your service provider class is a singleton and you need to access the model for the view user details. I would do it in the following manner:
JMUserDetailModel *myModel = [[[JMServiceProvider sharedInstance] modelProvider] userDetailModel];
This means that you would create a JMServiceProvider class for registering services, and being able to retreive these services. These services act a bit like a singleton, however if you need to unit test your code, then registering a different service that acts in the same way as the original is just a piece of cake.
Hope this answers your question.
EDIT: And read this article: http://martinfowler.com/articles/injection.html - a very good one explaining service oriented architectures as well ...
Look in to singletons. They can be a more elegant way to manage global data.