I have subclassed AFNetworking's AFHTTPSessionManager to create my own http client, I wrote a lot of categories, utilities methods, oauth2, retry login and whatnot.
I have this method to create the sharedSession:
+ (MTHTTPClient *)sharedSession {
static MTHTTPClient *sharedSession = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSURL *baseURL = [NSURL URLWithString:[NSString stringWithFormat:#"%#://%#:%#", kABXMyAppProtocol, kABXMyAppHost, kABXMyAppPort]];
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
...
});
return sharedSession;
}
and everything is fine.
Now I have this requirement to create another client but just with a different NSURLSessionConfiguration, for background download/uploads.
I would like to retain all the niceties and categories I built around this http client.
I'm unsure how to proceed, building another class (or singleton subclass, which kinda smells) seems to be not really viable due to the amount of logic I have to duplicate.
Creating another instance method like the one shown above would work? It's my understanding that the purpose of a singleton is to keep only one instance of the class around, so it may be a bad idea or not work at all.
Yes, it’s totally cool to create another singleton. There’s nothing magic about a singleton, it’s just an instance you create and re-use. You could have one or a thousand. As long as they’re stored in different static variables you’ll be fine.
Related
Method swizzling is used in the following singleton initializer but i am not sure about thread safety of swizzling.
What happens while a thread is about to call a method which is about to be swizzled by another method?
Is it safe to swizzle in any time, while there are threads about to call that method? Answer with official references please. Thanks
#import <dispatch/dispatch.h>
#import <objc/runtime.h>
#implementation MySingleton
static MySingleton * __singleton = nil;
+ (MySingleton *) sharedInstance_accessor
{
return ( __singleton );
}
+ (MySingleton *) sharedInstance
{
static dispatch_once_t __once = 0;
dispatch_once( &__once, ^{
__singleton = [[self alloc] init];
Method plainMethod = class_getInstanceMethod( self, #selector(sharedInstance) );
Method accessorMethod = class_getInstanceMethod( self, #selector(sharedInstance_accessor) );
method_exchangeImplementations( plainMethod, accessorMethod );
});
return ( __singleton );
}
#end
https://gist.github.com/MSch/943369
I doubt there is an official reference on this, but none is needed.
First, the executable code of the method is not un-mapped from memory. Thus, it doesn't matter which implementation is installed, the prior implementation is still available for execution.
That does mean, however, that you have to ensure that your data management is thread safe (which it is, assuming no one tries to call sharedInstance_accessor directly).
So that leaves a question as to whether method_exchangeImplementations() is thread safe. The source says it is (and it was not several major release prior) and so does the documentation.
As Brad Allred said, this is unlikely to be an optimization worth pursuing.
According to the documentation, method_exchangeImplementations() is atomic. Presumably that means that if one of the two methods being exchanged is called from another thread at the same time as method_exchangeImplementations() is being run, it may get the previous (non-swapped) method, but it won't get something inconsistent (e.g. won't crash).
Note that dispatch_once() is thread safe, and also means that as long as all references to the singleton instance are obtained via +sharedInstance, no thread will have a reference to the object before the swizzling is complete.
Finally, I don't normally like adding this kind of thing to answers, because I realize that sometimes questioners are just trying to learn more about how things work, rather than trying to write production code. However, if you're planning to use this in real, shipping code, you should rethink it. Swizzling tends to be a "bad code smell", and it's likely that there's a better way to do whatever it is you're trying to accomplish (which is still not clear to me).
Maybe a stupid question to ask but I need some confirmations on it.
Usually, when I deal with objects that can be used multiple times within my application I use an approach like the following.
Create an extension, say for example NSDecimalNumber+Extension, or a class utility where a number formatter is created like the following.
+ (NSNumberFormatter*)internal_sharedNumberFormatter
{
static NSNumberFormatter* _internal_numberFormatter = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_internal_numberFormatter = [[NSNumberFormatter alloc] init];
// other configurations here...
});
return _internal_numberFormatter;
}
+ (NSString*)stringRepresentationOfDecimalNumber:(NSDecimalNumber*)numberToFormat
{
NSString *stringRepresentation = [[self class] internal_sharedNumberFormatter] stringFromNumber:numberToFormat];
return stringRepresentation;
}
This approach is quite good since, for example, formatters are expensive to create. But it could be applied to other situations as well.
Now, my questions is the following.
Does this approach is also valid in situations where different path of execution (different threads) are involved?
So, if I call first stringRepresentationOfDecimalNumber on the main thread and then in a different thread, what could happen?
I think is valid to perform different calls to stringRepresentationOfDecimalNumber in different threads since the shared formatter, in this case, is reading only, but I would like to have a reply from experts.
Thanks in advance.
NSNumberFormatter is mutable, so it is generally not thread safe and cited in Thread Safety Summary (see the "Thread-Unsafe Classes" section) in the non thread safe classes list.
But if you treat your object as an immutable object, you don't have to worry about race conditions. So for example, you cannot change the format if there are multiple threads accessing the formatter. If _internal_numberFormatter isn't altered in any way, and you have just these two methods in the category, you should consider it thread safe.
OK, I know this question might seem irrelevant or too basic, but - since I always want to know what I'm doing and why I'm doing it, if it fits my design - please shed some light.
So, here's what I need :
Let's say we've got a class
We want to use its methods from pretty much anywhere
Instead of passing an object around, I decided to go for class methods and pseudo-global instances
So, let's say we've got a class named "MyDocumentManager".
This is what I usually do :
+ (MyDocumentManager*)documentManager
{
MyDocumentManager* newDocumentManager = [[MyDocumentManager alloc] init];
if (newDocumentManager)
{
// initialize that new document manager
}
return newDocumentManager;
}
And then use it like :
[[MyDocumentManager documentManager] someMethod];
However, I usually see people suggesting something like :
+ (MyDocumentManager*)sharedManager
{
static dispatch_once_t pred;
static MyDocumentManager *sharedManager;
dispatch_once(&pred, ^{
sharedManager = [[MyDocumentManager alloc] init];
});
return sharedManager;
}
So, here's my questions :
Is is the same thing?
If not, what is the difference?
What are the pros/cons of its approach? (in terms of memory/speed/etc)
Which one should I use and why?
Do they both fit what I need them for?
Is it the same thing?
No.
If not, what is the difference?
What you have doesn't implement a singleton, since it allocates a new instance of the class upon every function call. It's rather called a factory method. The definition of a singleton is that a certain class method always returns the same instance of the class.
Which one should I use and why?
You should generally avoid using singletons, because it's often considered bad practice, although there are cases when it's handy to have them. For example, if you have a class that uses encapsulated data but you only need quasi class-level methods, then it's better to implement a singleton with properly placed instance variables than implement class methods and tons of global/static variables (this is because in Objective-C, classes can't have member variables, only objects).
Do they both fit what I need them for?
You decide that.
The code you pasted in "what I usually do" is broken. It doesn't return a singleton. It returns a brand new object every time you call it (and if this isn't ARC then it's leaking it too).
The code you pasted as what people suggest is the correct code. Not only does it return a shared object each time, without leaking, but it's also thread-safe (so far as initialization of the object is concerned; it doesn't say anything about whether use of the object is thread-safe).
I need a string->string mapping to be used at runtime (think NSDictionary), except the mapping will NEVER change after build-time.
The naive solution is to just use an NSDictionary, but there has to be a more optimal way to do this, no?
Optimal in the sense that if the mapping is known at compile-time, and known to never change, the compiler should be able to do the mapping at compile-time. An NSDictionary needs to do a hash lookup at runtime. I know it's constant time, but it just feels a bit "unclean" to me...
You could hard code your NSDictionary if that isn't too cumbersome (i.e. it's not huge), or you could create a plist and include it in your app bundle. Then at app launch, read the dictionary from the plist (a couple lines of code). Each of these approaches is about the same effort. The advantage of using a plist is that if you have to change it, you are editing the plist, not code.
A static NSDictionary is the right tool for this. You typically initialize these with an +initialize method:
static NSDictionary *kDictionary;
+ (void)initialize {
if (self == [MYClass class]) {
kDictionary = [[NSDictionary alloc] initWith...];
}
}
initialize is called one time per class, with thread safety, immediately before the first requested method is called on that class (usually this first method is +alloc). The self test is because subclasses will automatically call their [super initialize], and you generally don't want to run this more than once in that case.
I have a singleton class, and can't unit test their code.
I have test like:
Db *db = [[Db alloc] initWithName:#"sample.db"];
[db createDb];
STAssertEquals([db existDb],YES,#"The db is not created!");
But only work the first. When the second is executed, I always get "null" from the initWithName method. When I remove the singleton support code, all work as expected.
I could hack the testing (but I don't know how right now) but wonder if exist a "poper" way to deal with this.
The singleton is located here: http://code.google.com/p/chibiorm/source/browse/trunk/src/Db.m
Singletons are hard to unit test and are sometimes the result of poor design.
My recommendation would be to think hard about whether you really need a singleton in the first place.
Maybe you could use the Factory pattern and create a factory that hands out only one instance (effectively your singleton). Then the implementation is not a singleton and you can unit test it to your hearts content.
The only drawback is that you are not protected by the language to create your own instance if you don't retrieve it from the factory. In C++ you may overcome this by making the constructor private and the factory and the unit test friends. I am not sure if Objective-C has a similar feature.
I think you shouldn't return nil on the second alloc but raise an exception. If you want to use a singleton you should not try to create two :).
However, if I decide to create a singleton my class looks like:
#implementation MySingleton
static id _instance = nil;
+ instance
{
if (_instance == nil) {
// alloc/init
_instance = [[self alloc] init];
…
}
return _instance;
}
…
#end
As you can see I am not enforcing that there may never be more than one instance. Instead I am using the convention to get the instance only with the instance method.
The guy here has written what I would have written as the answer, which is use categories to provide differnet instances from your singleton methods as needed.
http://twobitlabs.com/2011/02/mocking-singletons-with-ocmock/
The other guys above who are all pontificating their opinions of "singletons are bad m'kay" should be ignored. The first thing I did when I switched to objective c was write an iOC library, which I never used because I realised that objective c is NOT java, so please ignore people who bleet on about about java dogma : it doens't always apply to objective c.